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

FREE BetterLoot : 3.5.9 3.5.9

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Rust;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core.Configuration;
using Random = System.Random;
using Oxide.Core;
using Oxide.Core.Plugins;
using ConVar;

namespace Oxide.Plugins
{
    [Info("BetterLoot", "Tryhard & Khan", "3.5.9")]
    [Description("A light loot container modification system")]
    public class BetterLoot : RustPlugin
    {
        #region Fields

        [PluginReference] Plugin CustomLootSpawns;
        
        private static BetterLoot _instance;
        private static PluginConfig _config;
        private bool Changed = true;
        private bool initialized;
        private double baseItemRarity = 2;
        private int populatedContainers;
        private const string Admin = "betterloot.admin";
        
        StoredExportNames storedExportNames = new StoredExportNames();
        StoredBlacklist storedBlacklist = new StoredBlacklist();
        Random rng = new Random();
        Dictionary<string, List<string>[]> Items = new Dictionary<string, List<string>[]>();
        Dictionary<string, List<string>[]> Blueprints = new Dictionary<string, List<string>[]>();
        Dictionary<string, int[]> itemWeights = new Dictionary<string, int[]>();
        Dictionary<string, int[]> blueprintWeights = new Dictionary<string, int[]>();
        Dictionary<string, int> totalItemWeight = new Dictionary<string, int>();
        Dictionary<string, int> totalBlueprintWeight = new Dictionary<string, int>();

        List<Item> items = new List<Item>();
        List<string> itemNames = new List<string>();
        List<int> itemBlueprints = new List<int>();

        private static int RarityIndex(Rarity rarity)
        {
            switch (rarity)
            {
                case Rarity.None: return 0;
                case Rarity.Common: return 1;
                case Rarity.Uncommon: return 2;
                case Rarity.Rare: return 3;
                case Rarity.VeryRare: return 4;
            }
            return -1;
        }

        #endregion

        #region DataFile

        DynamicConfigFile lootTable;
        Dictionary<string, object> lootTables = null;
        DynamicConfigFile getFile(string file) => Interface.Oxide.DataFileSystem.GetDatafile($"{Name}/{file}");
        bool chkFile(string file) => Interface.Oxide.DataFileSystem.ExistsDatafile($"{Name}/{file}");

        private class StoredExportNames
        {
            public int version;
            public Dictionary<string, string> AllItemsAvailable = new Dictionary<string, string>();
        }
        
        private int ItemWeight(double baseRarity, int index) { return (int)(Math.Pow(baseRarity, 4 - index) * 1000); }
        
        private object GetAmounts(ItemAmount amount, int mul = 1)
        {
            if (amount.itemDef.isWearable || (amount.itemDef.condition.enabled && amount.itemDef.GetComponent<ItemModDeployable>() == null))
                mul = 1;
            object options = new Dictionary<string, object>
            {
                ["Min"] = (int)amount.amount * mul,
                ["Max"] = ((ItemAmountRanged)amount).maxAmount > 0f &&
                          ((ItemAmountRanged)amount).maxAmount > amount.amount
                    ? (int)((ItemAmountRanged)amount).maxAmount * mul
                    : (int)amount.amount * mul,
            };
            return options;
        }
        
        private void GetLootSpawn(LootSpawn lootSpawn, ref Dictionary<string, object> items)
        {
            if (lootSpawn.subSpawn != null && lootSpawn.subSpawn.Length > 0)
            {
                foreach (var entry in lootSpawn.subSpawn)
                    GetLootSpawn(entry.category, ref items);
                return;
            }
            if (lootSpawn.items != null && lootSpawn.items.Length > 0)
            {
                foreach (var amount in lootSpawn.items)
                {
                    object options = GetAmounts(amount, 1);
                    string itemName = amount.itemDef.shortname;
                    if (amount.itemDef.spawnAsBlueprint)
                        itemName += ".blueprint";
                    if (!items.ContainsKey(itemName))
                        items.Add(itemName, options);
                }
            }
        }
        
        private void LoadAllContainers()
        {
            try { lootTable = getFile("LootTables"); }
            catch (JsonReaderException e)
            {
                PrintWarning($"JSON error in 'LootTables' > Line: {e.LineNumber} | {e.Path}");
                Interface.GetMod().UnloadPlugin(Name);
                return;
            }
            lootTables = new Dictionary<string, object>();
            lootTables = lootTable["LootTables"] as Dictionary<string, object>;
            if (lootTables == null)
                lootTables = new Dictionary<string, object>();
            bool wasAdded = false;
            foreach (var lootPrefab in _config.Generic.WatchedPrefabs)
            {
                if (!lootTables.ContainsKey((string)lootPrefab))
                {
                    var loot = GameManager.server.FindPrefab((string)lootPrefab)?.GetComponent<LootContainer>();
                    if (loot == null)
                        continue;
                    var container = new Dictionary<string, object>();
                    container.Add("Enabled", !((string)lootPrefab).Contains("bradley_crate") && !((string)lootPrefab).Contains("heli_crate"));
                    container.Add("Scrap", loot.scrapAmount);
                    int slots = 0;
                    if (loot.LootSpawnSlots.Length > 0)
                    {
                        LootContainer.LootSpawnSlot[] lootSpawnSlots = loot.LootSpawnSlots;
                        for (int i = 0; i < lootSpawnSlots.Length; i++)
                            slots += lootSpawnSlots[i].numberToSpawn;
                    }
                    else
                        slots = loot.maxDefinitionsToSpawn;
                    container.Add("ItemsMin", slots);
                    container.Add("ItemsMax", slots);
                    container.Add("MaxBPs", 1);
                    var itemList = new Dictionary<string, object>();
                    if (loot.lootDefinition != null)
                        GetLootSpawn(loot.lootDefinition, ref itemList);
                    else if (loot.LootSpawnSlots.Length > 0)
                    {
                        LootContainer.LootSpawnSlot[] lootSpawnSlots = loot.LootSpawnSlots;
                        foreach (var lootSpawnSlot in lootSpawnSlots)
                        {
                            GetLootSpawn(lootSpawnSlot.definition, ref itemList);
                        }
                    }
                    container.Add("ItemList", itemList);
                    lootTables.Add((string)lootPrefab, container);
                    wasAdded = true;
                }

            }
            if (wasAdded)
            {
                lootTable.Set("LootTables", lootTables);
                lootTable.Save();
            }
            wasAdded = false;
            bool wasRemoved = false;
            int activeTypes = 0;
            foreach (var lootTable in lootTables.ToList())
            {
                var loot = GameManager.server.FindPrefab(lootTable.Key)?.GetComponent<LootContainer>();
                if (loot == null)
                {
                    lootTables.Remove(lootTable.Key);
                    wasRemoved = true;
                    continue;
                }
                var container = lootTable.Value as Dictionary<string, object>;
                if (!container.ContainsKey("Enabled"))
                {
                    container.Add("Enabled", true);
                    wasAdded = true;
                }
                if ((bool)container["Enabled"])
                    activeTypes++;
                if (!container.ContainsKey("Scrap"))
                {
                    container.Add("Scrap", loot.scrapAmount);
                    wasAdded = true;
                }

                int slots = 0;
                if (loot.LootSpawnSlots.Length > 0)
                {
                    LootContainer.LootSpawnSlot[] lootSpawnSlots = loot.LootSpawnSlots;
                    for (int i = 0; i < lootSpawnSlots.Length; i++)
                        slots += lootSpawnSlots[i].numberToSpawn;
                }
                else
                    slots = loot.maxDefinitionsToSpawn;
                if (!container.ContainsKey("MaxBPs"))
                {
                    container.Add("MaxBPs", 1);
                    wasAdded = true;
                }
                if (!container.ContainsKey("ItemsMin"))
                {
                    container.Add("ItemsMin", slots);
                    wasAdded = true;
                }
                if (!container.ContainsKey("ItemsMax"))
                {
                    container.Add("ItemsMax", slots);
                    wasAdded = true;
                }
                if (!container.ContainsKey("ItemsMax"))
                {
                    container.Add("ItemsMax", slots);
                    wasAdded = true;
                }
                if (!container.ContainsKey("ItemList"))
                {
                    var itemList = new Dictionary<string, object>();
                    if (loot.lootDefinition != null)
                        GetLootSpawn(loot.lootDefinition, ref itemList);
                    else if (loot.LootSpawnSlots.Length > 0)
                    {
                        LootContainer.LootSpawnSlot[] lootSpawnSlots = loot.LootSpawnSlots;
                        for (int i = 0; i < lootSpawnSlots.Length; i++)
                        {
                            LootContainer.LootSpawnSlot lootSpawnSlot = lootSpawnSlots[i];
                            GetLootSpawn(lootSpawnSlot.definition, ref itemList);
                        }
                    }
                    container.Add("ItemList", itemList);
                    wasAdded = true;
                }
                Items.Add(lootTable.Key, new List<string>[5]);
                Blueprints.Add(lootTable.Key, new List<string>[5]);
                for (var i = 0; i < 5; ++i)
                {
                    Items[lootTable.Key][i] = new List<string>();
                    Blueprints[lootTable.Key][i] = new List<string>();
                }
                foreach (var itemEntry in container["ItemList"] as Dictionary<string, object>)
                {
                    bool isBP = itemEntry.Key.EndsWith(".blueprint") ? true : false;
                    var def = ItemManager.FindItemDefinition(itemEntry.Key.Replace(".blueprint", ""));

                    if (def != null)
                    {
                        if (isBP && def.Blueprint != null && def.Blueprint.isResearchable)
                        {
                            int index = (int)def.rarity;
                            if (!Blueprints[lootTable.Key][index].Contains(def.shortname))
                                Blueprints[lootTable.Key][index].Add(def.shortname);
                        }
                        else
                        {
                            int index = 0;
                            object indexoverride;
                            if (_config.Rare.Override.TryGetValue(def.shortname, out indexoverride))
                                index = Convert.ToInt32(indexoverride);
                            else
                                index = (int)def.rarity;
                            if (!Items[lootTable.Key][index].Contains(def.shortname))
                                Items[lootTable.Key][index].Add(def.shortname);
                        }
                    }
                }
                totalItemWeight.Add(lootTable.Key, 0);
                totalBlueprintWeight.Add(lootTable.Key, 0);
                itemWeights.Add(lootTable.Key, new int[5]);
                blueprintWeights.Add(lootTable.Key, new int[5]);
                for (var i = 0; i < 5; ++i)
                {
                    totalItemWeight[lootTable.Key] += (itemWeights[lootTable.Key][i] = ItemWeight(baseItemRarity, i) * Items[lootTable.Key][i].Count);
                    totalBlueprintWeight[lootTable.Key] += (blueprintWeights[lootTable.Key][i] = ItemWeight(baseItemRarity, i) * Blueprints[lootTable.Key][i].Count);
                }

            }
            if (wasAdded || wasRemoved)
            {
                lootTable.Set("LootTables", lootTables);
                lootTable.Save();
            }
            lootTable.Clear();
            Puts($"Using '{activeTypes}' active of '{lootTables.Count}' supported containertypes");
        }

        private void SaveExportNames()
        {
            storedExportNames = Interface.GetMod().DataFileSystem.ReadObject<StoredExportNames>("BetterLoot\\NamesList");
            if (storedExportNames.AllItemsAvailable.Count == 0 || (int)storedExportNames.version != Rust.Protocol.network)
            {
                storedExportNames = new StoredExportNames();
                var exportItems = new List<ItemDefinition>(ItemManager.itemList);
                storedExportNames.version = Rust.Protocol.network;
                foreach (var it in exportItems)
                    storedExportNames.AllItemsAvailable.Add(it.shortname, it.displayName.english);
                Interface.GetMod().DataFileSystem.WriteObject("BetterLoot\\NamesList", storedExportNames);
                Puts($"Exported {storedExportNames.AllItemsAvailable.Count} items to 'NamesList'");
            }
        }
        
        private class StoredBlacklist
        {
            public List<string> ItemList = new List<string>();
        }

        private void LoadBlacklist()
        {
            storedBlacklist = Interface.GetMod().DataFileSystem.ReadObject<StoredBlacklist>("BetterLoot\\Blacklist");
            if (storedBlacklist.ItemList.Count != 0) return;
            Puts("No Blacklist found, creating new file...");
            storedBlacklist = new StoredBlacklist();
            storedBlacklist.ItemList.Add("flare");
            Interface.GetMod().DataFileSystem.WriteObject("BetterLoot\\Blacklist", storedBlacklist);
        }

        private void SaveBlacklist() => Interface.GetMod().DataFileSystem.WriteObject("BetterLoot\\Blacklist", storedBlacklist);
        
        #endregion

        #region Config

        private class PluginConfig : SerializableConfiguration
        {
            public Generic Generic = new Generic();
            public Loot Loot = new Loot();
            [JsonProperty("Rarity")]
            public Rare Rare = new Rare();

            public string ToJson() => JsonConvert.SerializeObject(this);
            public Dictionary<string, object> ToDictionary() => JsonConvert.DeserializeObject<Dictionary<string, object>>(ToJson());
        }
        
        private class Generic
        {
            public double blueprintProbability = 0.11;
            public bool listUpdatesOnLoaded = true;
            public bool removeStackedContainers = true;
            public List<object> WatchedPrefabs = new List<object>();
        }

        private class Loot
        {
            public bool enableHammerLootCycle = false;
            public double hammerLootCycleTime = 3.0;
            public int lootMultiplier = 1;
            public int scrapMultiplier = 1;
        }

        private class Rare
        {
            public Dictionary<string, object> Override = new Dictionary<string, object>
            {
                {"autoturret", 4},
                {"lmg.m249", 4},
                {"targeting.computer", 3},
            };
        }
        
        private void CheckConfig()
        {
            foreach (GameManifest.PrefabProperties category in GameManifest.Current.prefabProperties)
            {
                if (!(category.name.Contains("resource/loot") || 
                      category.name.Contains("misc/supply drop/supply_drop") || 
                      category.name.Contains("/npc/m2bradley/bradley_crate") || 
                      category.name.Contains("/npc/patrol helicopter/heli_crate") || 
                      category.name.Contains("/deployable/chinooklockedcrate/chinooklocked") || 
                      category.name.Contains("/deployable/chinooklockedcrate/codelocked") || 
                      category.name.Contains("prefabs/radtown") || 
                      category.name.Contains("props/roadsigns")) ||
                    category.name.Contains("radtown/ore") || 
                    category.name.Contains("static") || 
                    category.name.Contains("/spawners") || 
                    category.name.Contains("radtown/desk") || 
                    category.name.Contains("radtown/loot_component_test")) continue;
                if (!_config.Generic.WatchedPrefabs.Contains(category.name))
                {
                    _config.Generic.WatchedPrefabs.Add(category.name);
                }
            }
            SaveConfig();
        }
        
        protected override void LoadDefaultConfig() => _config = new PluginConfig();
        
        protected override void LoadConfig()
        {
            base.LoadConfig();

            try
            {
                _config = Config.ReadObject<PluginConfig>();

                if (_config == null)
                {
                    PrintWarning($"Generating Config File for Better Loot");
                    throw new JsonException();
                }

                if (MaybeUpdateConfig(_config))
                {
                    PrintWarning("Configuration appears to be outdated; updating and saving Better Loot");
                    SaveConfig();
                }
            }
            catch (Exception ex)
            {
                PrintWarning("Failed to load Better Loot config file (is the config file corrupt?) (" + ex.Message + ")");
            }
        }
        protected override void SaveConfig()
        {
            //PrintToConsole($"Configuration changes saved to {Name}.json");
            PrintWarning($"Configuration changes saved to {Name}.json");
            Config.WriteObject(_config, true);
        }

        #endregion

        #region Updater

        internal class SerializableConfiguration
        {
            public string ToJson() => JsonConvert.SerializeObject(this);

            public Dictionary<string, object> ToDictionary() => JsonHelper.Deserialize(ToJson()) as Dictionary<string, object>;
        }

        private static class JsonHelper
        {
            public static object Deserialize(string json) => ToObject(JToken.Parse(json));

            private static object ToObject(JToken token)
            {
                switch (token.Type)
                {
                    case JTokenType.Object:
                        return token.Children<JProperty>().ToDictionary(prop => prop.Name, prop => ToObject(prop.Value));
                    case JTokenType.Array:
                        return token.Select(ToObject).ToList();

                    default:
                        return ((JValue) token).Value;
                }
            }
        }

        private bool MaybeUpdateConfig(SerializableConfiguration config)
        {
            var currentWithDefaults = config.ToDictionary();
            var currentRaw = Config.ToDictionary(x => x.Key, x => x.Value);
            return MaybeUpdateConfigDict(currentWithDefaults, currentRaw);
        }

        private bool MaybeUpdateConfigDict(Dictionary<string, object> currentWithDefaults, Dictionary<string, object> currentRaw)
        {
            bool changed = false;

            foreach (var key in currentWithDefaults.Keys)
            {
                object currentRawValue;
                if (currentRaw.TryGetValue(key, out currentRawValue))
                {
                    var defaultDictValue = currentWithDefaults[key] as Dictionary<string, object>;
                    var currentDictValue = currentRawValue as Dictionary<string, object>;

                    if (defaultDictValue != null)
                    {
                        if (currentDictValue == null)
                        {
                            currentRaw[key] = currentWithDefaults[key];
                            changed = true;
                        }
                        else if (MaybeUpdateConfigDict(defaultDictValue, currentDictValue))
                            changed = true;
                    }
                }
                else
                {
                    currentRaw[key] = currentWithDefaults[key];
                    changed = true;
                }
            }

            return changed;
        }

        #endregion

        #region Oxide

        private void Init()
        {
            CheckConfig();
            LoadBlacklist();
            _instance = this;
        }

        private void OnServerInitialized()
        {
            ItemManager.Initialize();
            permission.RegisterPermission(Admin, this);
            LoadAllContainers();
            UpdateInternals(_config.Generic.listUpdatesOnLoaded);
        }

        private void Unload()
        {
            var gameObjects = UnityEngine.Object.FindObjectsOfType<HammerHitLootCycle>().ToList();
            if (gameObjects.Count > 0) 
            {
                foreach (var objects in gameObjects) 
                {
                    UnityEngine.Object.Destroy(objects);
                }
            }
            _instance = null;
        }
        
        private object OnLootSpawn(LootContainer container)
        {
            if (!initialized || container == null)
                return null;
            if (CustomLootSpawns != null && CustomLootSpawns.Call<bool>("IsLootBox", container as BaseEntity))
                return null;
            if (PopulateContainer(container))
            {
                ItemManager.DoRemoves();
                return true;
            }
            return null;
        }
        
        //void OnLootEntity(BasePlayer player, BaseEntity target)
        //{
        //Puts($"{player.displayName} looted {target.PrefabName}");
        //}

        #endregion

        #region Core
        
        private bool PopulateContainer(LootContainer container)
        {
            Dictionary<string, object> con;
            object containerobj;
            if (!lootTables.TryGetValue(container.PrefabName, out containerobj))
                return false;
            con = containerobj as Dictionary<string, object>;
            if (!(bool)con["Enabled"])
                return false;
            var lootitemcount = (con["ItemList"] as Dictionary<string, object>)?.Count();
            int itemCount = Mathf.RoundToInt(UnityEngine.Random.Range(Convert.ToSingle(Mathf.Min((int)con["ItemsMin"], (int)con["ItemsMax"])) * 100f, Convert.ToSingle(Mathf.Max((int)con["ItemsMin"], (int)con["ItemsMax"])) * 100f) / 100f);
            if (lootitemcount > 0 && itemCount > lootitemcount && lootitemcount < 36)
                itemCount = (int)lootitemcount;
            if (container.inventory == null)
            {
                container.CreateInventory(true);
                container.OnInventoryFirstCreated(container.inventory);
            }
            else
            {
                container.inventory.Clear();
                container.inventory.capacity = 36;
                ItemManager.DoRemoves();
            }

            itemNames.Clear();
            items.Clear();
            itemBlueprints.Clear();

            var maxRetry = 10;
            for (int i = 0; i < itemCount; ++i)
            {
                if (maxRetry == 0)
                {
                    break;
                }
                var item = MightyRNG(container.PrefabName, itemCount, (bool)(itemBlueprints.Count >= (int)con["MaxBPs"]));

                if (item == null)
                {
                    --maxRetry;
                    --i;
                    continue;
                }
                if (itemNames.Contains(item.info.shortname) || (item.IsBlueprint() && itemBlueprints.Contains(item.blueprintTarget)))
                {
                    item.Remove();
                    --maxRetry;
                    --i;
                    continue;
                }
                else
                    if (item.IsBlueprint())
                    itemBlueprints.Add(item.blueprintTarget);
                else
                    itemNames.Add(item.info.shortname);
                items.Add(item);
                if (storedBlacklist.ItemList.Contains(item.info.shortname)) 
                {
                    items.Remove(item);
					item.Remove(); // broken item fix
                }
            }
            foreach (var item in items.Where(x => x != null && x.IsValid()))
                if (!item.MoveToContainer(container.inventory, -1, false)) { item.DoRemove(); } // broken item fix / fixes full container 
            if ((int)con["Scrap"] > 0)
            {
                int scrapCount = (int)con["Scrap"];
                Item item = ItemManager.Create(ItemManager.FindItemDefinition("scrap"), scrapCount * _config.Loot.scrapMultiplier, 0uL); 
                if (!item.MoveToContainer(container.inventory, -1, false)) { item.DoRemove(); } // broken item fix
            }
            container.inventory.capacity = container.inventory.itemList.Count;
            container.inventory.MarkDirty();
            container.SendNetworkUpdate();
            populatedContainers++;
            return true;
        }

        private void UpdateInternals(bool doLog)
        {
            SaveExportNames();
            if (Changed)
            {
                SaveConfig();
                Changed = false;
            }
            Puts("Updating internals...");
            populatedContainers = 0;
            NextTick(() =>
            {
                if (_config.Generic.removeStackedContainers)
                    FixLoot();
                foreach (var container in BaseNetworkable.serverEntities.Where(p => p != null && p as BaseEntity != null && p is LootContainer).Cast<LootContainer>().ToList())
                {
                    if (container == null)
                        continue;
                    if (CustomLootSpawns != null && CustomLootSpawns.Call<bool>("IsLootBox", container as BaseEntity))
                        continue;
                    if (PopulateContainer(container))
                        populatedContainers++;
                }
                
                Puts($"Populated '{populatedContainers}' supported containers.");
                initialized = true;
                populatedContainers = 0;
                ItemManager.DoRemoves();
            });
        }
        
        private void FixLoot()
        {
            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 pos = new Vector2(box.transform.position.x, box.transform.position.z);

                if (++antirace > racelimit)
                {
                    return;
                }

                var next = i + 1;
                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 < 0.25f)
                    {
                        spawns.RemoveAt(next);
                        count--;
                        (box2 as BaseEntity).KillMessage();
                        deleted++;
                    }
                    else break;
                }
            }

            if (deleted > 0)
                Puts($"Removed {deleted} stacked LootContainer");
            else
                Puts($"No stacked LootContainer found.");
            ItemManager.DoRemoves();
        }
        
        private Item MightyRNG(string type, int itemCount, bool blockBPs = false)
        {
            bool asBP = rng.NextDouble() < _config.Generic.blueprintProbability && !blockBPs;
            List<string> selectFrom;
            int limit = 0;
            string itemName;
            Item item;
            int maxRetry = 10 * itemCount;
            do
            {
                selectFrom = null;
                item = null;
                if (asBP)
                {
                    var r = rng.Next(totalBlueprintWeight[type]);
                    for (var i = 0; i < 5; ++i)
                    {
                        limit += blueprintWeights[type][i];
                        if (r < limit)
                        {
                            selectFrom = Blueprints[type][i];
                            break;
                        }
                    }
                }
                else
                {
                    var r = rng.Next(totalItemWeight[type]);
                    for (var i = 0; i < 5; ++i)
                    {
                        limit += itemWeights[type][i];
                        if (r < limit)
                        {
                            selectFrom = Items[type][i];
                            break;
                        }
                    }
                }
                if (selectFrom == null)
                {
                    if (--maxRetry <= 0)
                        break;
                    continue;
                }
                itemName = selectFrom[rng.Next(0, selectFrom.Count)];
                ItemDefinition itemDef = ItemManager.FindItemDefinition(itemName);
                if (asBP && itemDef.Blueprint != null && itemDef.Blueprint.isResearchable)
                {
                    var blueprintBaseDef = ItemManager.FindItemDefinition("blueprintbase");
                    item = ItemManager.Create(blueprintBaseDef, 1, 0uL);
                    item.blueprintTarget = itemDef.itemid;
                }
                else
                    item = ItemManager.CreateByName(itemName, 1);
                if (item == null || item.info == null)
                    continue;
                break;
            } while (true);
            if (item == null)
                return null;
            object itemOptions;
            if (((lootTables[type] as Dictionary<string, object>)["ItemList"] as Dictionary<string, object>).TryGetValue(item.info.shortname, out itemOptions))
            {
                Dictionary<string, object> options = itemOptions as Dictionary<string, object>;
                item.amount = UnityEngine.Random.Range(Math.Min((int)options["Min"], (int)options["Max"]), Math.Max((int)options["Min"], (int)options["Max"])) * _config.Loot.lootMultiplier;
                //if (options.ContainsKey("SkinId"))
                    //item.skin = (uint)options["SkinId"];

            }
            item.OnVirginSpawn();
            return item;
        }
        
        private bool ItemExists(string name)
        {
            // remove useless loop
            ItemDefinition itemDef = ItemManager.itemList.Find((ItemDefinition x) => x.shortname == name);
            if (itemDef != null) return true;            
            return false;
        }
        
        private bool isSupplyDropActive()
        {
            Dictionary<string, object> con;
            object containerobj;
            if (!lootTables.TryGetValue("assets/prefabs/misc/supply drop/supply_drop.prefab", out containerobj))
                return false;
            con = containerobj as Dictionary<string, object>;
            if ((bool)con["Enabled"])
                return true;
            return false;
        }

        #endregion

        [ChatCommand("blacklist")]
        private void CmdChatBlacklistNew(BasePlayer player, string command, string[] args)
        {
            if (!initialized)
            {
                SendReply(player, BLLang( "initialized")); return;
            }
            if (!permission.UserHasPermission(player.UserIDString, Admin))
            {
                SendReply(player, BLLang("perm")); return;
            }
            if (args.Length == 0)
            {
                if (storedBlacklist.ItemList.Count == 0)
                {
                    SendReply(player, BLLang("none"));
                }
                else
                {
                    var sb = new StringBuilder();
                    foreach (var item in storedBlacklist.ItemList)
                    {
                        if (sb.Length > 0)
                            sb.Append(", ");
                        sb.Append(item);
                    }
                    SendReply(player, BLLang("blocked", player.UserIDString, sb.ToString()));
                }
                return;
            }

            switch (args[0].ToLower())
            {
                case "additem":
                    if (!ItemExists(args[1]))
                    {
                        SendReply(player, BLLang("notvalid", player.UserIDString, args[1]));
                        return;
                    }
                    if (!storedBlacklist.ItemList.Contains(args[1]))
                    {
                        storedBlacklist.ItemList.Add(args[1]);
                        UpdateInternals(false);
                        SendReply(player, BLLang("blockedpass", player.UserIDString, args[1]));
                        SaveBlacklist();
                        return;
                    }
                    SendReply(player, BLLang("blockedtrue", player.UserIDString, args[1]));
                    break;
                case "deleteitem":
                    if (!ItemExists(args[1]))
                    {
                        SendReply(player, BLLang("notvalid", player.UserIDString, args[1]));
                        return;
                    }
                    if (storedBlacklist.ItemList.Contains(args[1]))
                    {
                        storedBlacklist.ItemList.Remove(args[1]);
                        UpdateInternals(false);
                        SendReply(player, BLLang("unblacklisted", player.UserIDString, args[1]));
                        SaveBlacklist();
                        return;
                    }
                    SendReply(player, BLLang("blockedfalse", player.UserIDString, args[1]));
                    break;
                default:
                    SendReply(player, BLLang("syntax"));
                    break;
            }
        }

        #region Hammer loot cycle

        object OnMeleeAttack(BasePlayer player, HitInfo c)
        {
            //Puts($"OnMeleeAttack works! You hit {c.HitEntity.PrefabName}"); DEBUG FOR TESTING
            var item = player.GetActiveItem();
            if (item.hasCondition) return null;
            //Puts($"{item.ToString()}");
            if (!player.IsAdmin || c.HitEntity.GetComponent<LootContainer>() == null || !item.ToString().Contains("hammer") || !_config.Loot.enableHammerLootCycle)  return null;
            var inv = c.HitEntity.GetComponent<StorageContainer>();
            inv.gameObject.AddComponent<HammerHitLootCycle>();
            player.inventory.loot.StartLootingEntity(inv, false);
            player.inventory.loot.AddContainer(inv.inventory);
            player.inventory.loot.SendImmediate();
            player.ClientRPCPlayer(null, player, "RPC_OpenLootPanel", inv.panelName);

            //Timer s = timer.Every(1f, () => { PopulateContainer(inv})
            return null;
            }

        private class HammerHitLootCycle : FacepunchBehaviour
        {
            private void Awake()
            {
                if (!_instance.initialized) return;
                InvokeRepeating(Repeater, (float)_config.Loot.hammerLootCycleTime, (float)_config.Loot.hammerLootCycleTime);
            }
            private void Repeater()
            {
                if (!enabled) return;
                LootContainer loot = GetComponent<LootContainer>();
                _instance.Puts($"{loot}");
                _instance.PopulateContainer(loot);
            }
            private void PlayerStoppedLooting(BasePlayer player)
            {
                //_instance.Puts($"Ended looting of the box"); Doesn't call but it works for a reason I don't quite understand
                CancelInvoke(Repeater);
                Destroy(this);
            }
        }

        #endregion

        #region Lang

        private string BLLang(string key, string id = null) => lang.GetMessage(key, this, id);
        private string BLLang(string key, string id = null, params object[] args) => string.Format(lang.GetMessage(key, this, id), args);
        
        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                { "initialized", "Plugin not enabled"},
                { "perm", "You are not authorized to use this command"},
                { "syntax", "Usage: /blacklist [additem|deleteitem] \"ITEMNAME\""},
                { "none", "There are no blacklisted items"},
                { "blocked", "Blacklisted items: {0}"},
                { "notvalid", "Not a valid item: {0}"},
                {"blockedpass", "The item '{0}' is now blacklisted"},
                {"blockedtrue", "The item '{0}' is already blacklisted}"},
                {"unblacklisted", "The item '{0}' has been unblacklisted"},
                {"blockedfalse", "The item '{0}' is not blacklisted"},
            }, this); //en
        }

        #endregion
    }
}

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