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

FREE MagicLoot : 1.0.5 1.0.5

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using Facepunch;
using Newtonsoft.Json;
using Oxide.Core;
using Rust;
namespace Oxide.Plugins {
    [Info("Magic Loot", "collect_vood", "1.0.5")]
    [Description("Simple components multiplier and loot system")]
    public class MagicLoot : CovalencePlugin {
#region Fields
        private bool _initialized = false;
        private readonly int _maxContainerSlots = 18;
        private int _scrapStack;
        private Dictionary<Rarity, List<string>> _sortedRarities;
        private Dictionary<int, List<ulong>> _skinsCache = new Dictionary<int, List<ulong>>();
        private Dictionary<LootSpawn, ItemAmountRanged[]> _originItemAmountRange = new Dictionary<LootSpawn, ItemAmountRanged[]>();
#endregion
#region Configuration
        private ConfigurationFile _configuration;
        public class ConfigurationFile {
            [JsonProperty(PropertyName = "General Settings")]
            public SettingsFile Settings = new SettingsFile();
            [JsonProperty(PropertyName = "Extra Loot")]
            public ExtraLootFile ExtraLoot = new ExtraLootFile();
            [JsonProperty(PropertyName = "Blacklisted Items (Item-Shortnames)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public List<string> BlacklistedItems = new List<string>() {
                "ammo.rocket.smoke"
            }
            ;
            [JsonProperty(PropertyName = "Blacklisted Workshop Skins (Workshop Ids)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public List<ulong> BlacklistSkins = new List<ulong>() {
                10180
            }
            ;
            [JsonProperty(PropertyName = "Manual Item Multipliers (Key: Item-Shortname, Value: Multiplier)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<string, float> ManualItemMultipliers = new Dictionary<string, float>();
            [JsonProperty(PropertyName = "Containers Data (Key: Container-Shortname, Value: Container Settings)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<string, ContainerData> ContainersData = new Dictionary<string, ContainerData>();
            [JsonProperty(PropertyName = "Debug")]
            public bool Debug = false;
        }
        public class SettingsFile {
            [JsonProperty(PropertyName = "General Item List Multiplier (All items in the 'Manual Item Multipliers' List)")]
            public float ItemListMultiplier = 1f;
            [JsonProperty(PropertyName = "Non Item List Multiplier (All items not listed in the 'Manual Item Multipliers' List)")]
            public float NonItemListMultiplier = 1f;
            [JsonProperty(PropertyName = "Limit Multipliers to Stacksizes")]
            public bool LimitToStacksizes = true;
            [JsonProperty(PropertyName = "Multiply Blueprints")]
            public bool BlueprintDuplication = false;
            [JsonProperty(PropertyName = "Disable Blueprint Drops")]
            public bool DisableBlueprints = false;
            [JsonProperty(PropertyName = "Random Workshop Skins")]
            public bool RandomWorkshopSkins = false;
            [JsonProperty(PropertyName = "Multiply Tea Buffs")]
            public bool MultiplyTeaBuff = false;
            [JsonProperty(PropertyName = "Force Custom Loot Tables for Default Loot on all Containers")]
            public bool ForceCustomLootTables = false;
        }
        public class ExtraLootFile {
            [JsonProperty(PropertyName = "Enabled")]
            public bool Enabled = false;
            [JsonProperty(PropertyName = "Extra Items Min")]
            public int ExtraItemsMin = 0;
            [JsonProperty(PropertyName = "Extra Items Max")]
            public int ExtraItemsMax = 0;
            [JsonProperty(PropertyName = "Prevent Duplicates")]
            public bool PreventDuplicates = true;
            [JsonProperty(PropertyName = "Prevent Duplicates Retries")]
            public int PreventDuplicatesRetries = 10;
            [JsonProperty(PropertyName = "Force Custom Loot Tables for Extra Loot on all Containers")]
            public bool ForceCustomLootTables = false;
        }
        public class ContainerData {
            [JsonProperty(PropertyName = "Enabled")]
            public bool Enabled = true;
            [JsonProperty(PropertyName = "Extra Items Min")]
            public int ExtraItemsMin = 0;
            [JsonProperty(PropertyName = "Extra Items Max")]
            public int ExtraItemsMax = 0;
            [JsonProperty(PropertyName = "Loot Multiplier")]
            public float Multiplier = 1f;
            [JsonProperty(PropertyName = "Utilize Vanilla Loot Tables on Default Loot")]
            public bool VanillaLootTablesDefault = true;
            [JsonProperty(PropertyName = "Utilize Vanilla Loot Tables on Extra Loot")]
            public bool VanillaLootTablesExtra = true;
            [JsonProperty(PropertyName = "Utilize Random Rarity (depending on Items ALREADY in the container)")]
            public bool RandomRarities = true;
            [JsonProperty(PropertyName = "Rarity To Use (ONLY if 'Utilize Vanilla Loot Tables' is FALSE & 'Utilize Random Rarity' is FALSE | 0 = None, 1 = Common, 2 = Uncommon, 3 = Rare, 4 = Very Rare)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public List<Rarity> Rarities = new List<Rarity>() {
                Rarity.Common, Rarity.Uncommon, Rarity.Rare, Rarity.VeryRare
            }
            ;
        }
        protected override void LoadDefaultConfig() {
            PrintWarning("Creating a new configuration file");
            _configuration = new ConfigurationFile();
            foreach (var itemDef in ItemManager.itemList) {
                if (itemDef.category != ItemCategory.Component) {
                    continue;
                }
                _configuration.ManualItemMultipliers.Add(itemDef.shortname, 1f);
            }
            _configuration.ManualItemMultipliers.Add("scrap", 1f);
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            _configuration = Config.ReadObject<ConfigurationFile>();
            SaveConfig();
        }
        protected override void SaveConfig() => Config.WriteObject(_configuration);
#endregion
#region Data
        private void LoadData() {
            _data = Interface.Oxide.DataFileSystem.ReadObject<DataFile>(Name);
            int count = 0;
            foreach (var item in ItemManager.itemList) {
                if (_data.Items.ContainsKey(item.shortname)) {
                    continue;
                }
                _data.Items.Add(item.shortname, item.stackable);
                count++;
            }
            SaveData();
            if (count > 0) {
                Puts($"Added {count} new items to the item list!");
            }
            //Determine if rarity system is needed
            if (_configuration.Settings.ForceCustomLootTables || _configuration.ExtraLoot.ForceCustomLootTables) {
                _sortedRarities = GetSortedRarities();
            }
            else {
                foreach (var container in _configuration.ContainersData) {
                    if (!container.Value.VanillaLootTablesDefault || !container.Value.VanillaLootTablesExtra) {
                        _sortedRarities = GetSortedRarities();
                        break;
                    }
                }
            }
            _scrapStack = _data.Items["scrap"];
        }
        private void SaveData() {
            Interface.Oxide.DataFileSystem.WriteObject(Name, _data);
        }
        private DataFile _data;
        public class DataFile {
            [JsonProperty(PropertyName = "Item Data (Key: Item Shortname, Value: Stacksize)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<string, int> Items = new Dictionary<string, int>();
        }
#endregion
#region Hooks
        private void OnServerInitialized() {
            _initialized = true;
            if (!_configuration.Settings.MultiplyTeaBuff) {
                Unsubscribe(nameof(OnBonusItemDrop));
            }
            LoadData();
            ModifyItemAmountRanges();
            AddMissingContainers();
            Puts($"Loaded at x{_configuration.Settings.NonItemListMultiplier} vanilla rate" + $" | Manual Item List at x{_configuration.Settings.ItemListMultiplier} rate [Extra Loot: {_configuration.ExtraLoot.Enabled}, Multiply Tea Buffs: {_configuration.Settings.MultiplyTeaBuff}]");
            RepopulateContainers();
        }
        private object OnLootSpawn(LootContainer container) {
            if (!_initialized || container?.inventory?.itemList == null) {
                return null;
            }
            ContainerData containerData;
            if (!_configuration.ContainersData.TryGetValue(container.ShortPrefabName, out containerData)) {
                _configuration.ContainersData.Add(container.ShortPrefabName, containerData = new ContainerData());
                SaveConfig();
            }
            if (IgnoreContainer(containerData)) {
                return null;
            }
            PopulateContainer(container, containerData);
            if (container.shouldRefreshContents && container.isLootable) {
                container.Invoke(new Action(container.SpawnLoot), UnityEngine.Random.Range(container.minSecondsBetweenRefresh, container.maxSecondsBetweenRefresh));
            }
            return container;
        }
        private void OnBonusItemDrop(Item item, BasePlayer player) {
            ReinforceRules(item, null);
        }
        private void Unload() {
            _initialized = false;
            RestoreItemAmountRanges();
            foreach (var container in UnityEngine.Object.FindObjectsOfType<LootContainer>()) {
                if (container?.inventory == null) {
                    continue;
                }
                container.SpawnLoot();
            }
        }
#endregion
#region Methods
        /// <summary>
        /// Adds missing containers to the configuration file
        /// </summary>
        private void AddMissingContainers() {
            int count = 0;
            foreach (var container in UnityEngine.Resources.FindObjectsOfTypeAll<LootContainer>()) {
                if (!container.enabled) {
                    continue;
                }
                ContainerData containerData;
                if (_configuration.ContainersData.TryGetValue(container.ShortPrefabName, out containerData)) {
                    continue;
                }
                _configuration.ContainersData.Add(container.ShortPrefabName, containerData = new ContainerData());
                count++;
            }
            if (count > 0) {
                Puts($"Added {count} missing containers to the config file.");
            }
        }
        /// <summary>
        /// Repopulates all LootContainers
        /// </summary>
        private void RepopulateContainers() {
            int count = 0;
            foreach (var container in UnityEngine.Object.FindObjectsOfType<LootContainer>()) {
                var containerData = _configuration.ContainersData[container.ShortPrefabName];
                if (IgnoreContainer(containerData)) {
                    continue;
                }
                container.inventory.Clear();
                ItemManager.DoRemoves();
                PopulateContainer(container, containerData);
                count++;
            }
            SaveConfig();
            Puts("Repopulated " + count.ToString() + " loot containers.");
        }
        /// <summary>
        /// Populates the Container
        /// </summary>
        /// <param name="container"></param>
        /// <param name="containerData"></param>
        private void PopulateContainer(LootContainer container, ContainerData containerData) {
            container.inventory.capacity = _maxContainerSlots;
            AddDefaultLoot(container, containerData);
            AddExtraLoot(container, containerData);
            RandomizeDurability(container);
            //Generate scrap late so it is in the last slot
            if (_scrapStack > 0) {
                container.GenerateScrap();
            }
            ReinforceRules(container, containerData);
        }
        /// <summary>
        /// Removes blacklisted items, applies item skins and applies multipliers
        /// </summary>
        /// <param name="container"></param>
        private void ReinforceRules(LootContainer container, ContainerData containerData) {
            for (int i = 0; i < container.inventory.itemList.Count; i++) {
                var item = container.inventory.itemList[i];
                ReinforceRules(item, containerData);
            }
        }
        /// <summary>
        /// Removes blacklisted item, applies item skin and applies multipliers
        /// </summary>
        /// <param name="item"></param>
        /// <param name="containerData"></param>
        private void ReinforceRules(Item item, ContainerData containerData = null) {
            if (_configuration.Settings.DisableBlueprints && item.IsBlueprint()) {
                item.info = ItemManager.FindItemDefinition(item.blueprintTarget);
                item.blueprintTarget = 0;
                item.maxCondition = item.info.condition.max;
                item.condition = item.info.condition.max;
                item.OnItemCreated();
            }
            if (!_configuration.Settings.BlueprintDuplication && item.IsBlueprint()) {
                return;
            }
            if (_configuration.Settings.RandomWorkshopSkins && item.info.shortname != "hazmatsuit") {
                var skinId = GetRandomSkin(item.info);
                ApplySkinToItem(item, skinId);
            }
            float multiplier = 1f;
            var inItemList = _configuration.ManualItemMultipliers.TryGetValue(item.info.shortname, out multiplier);
            if (!inItemList) {
                multiplier = 1f;
            }
            //Do not multiply
            if (multiplier == 0f) {
                return;
            }
            multiplier *= inItemList ? _configuration.Settings.ItemListMultiplier : _configuration.Settings.NonItemListMultiplier;
            if (containerData != null) {
                multiplier *= containerData.Multiplier;
            }
            var maxAmount = _data.Items[item.info.shortname];
            if (maxAmount <= 0) {
                PrintWarning($"Item '{item.info.shortname}' spawned with 0 amount...");
            }
            item.amount = _configuration.Settings.LimitToStacksizes ? (int)Math.Min(item.amount * multiplier, maxAmount) : (int)(item.amount * multiplier);
        }
        /// <summary>
        /// Returns a list of items where duplicated items are found
        /// </summary>
        /// <param name="item"></param>
        /// <param name="items"></param>
        /// <returns></returns>
        private void FindDuplicates(int itemId, List<Item> items, ref List<Item> duplicateItems) {
            foreach (var cItem in items) {
                if (cItem.info.itemid != itemId) {
                    continue;
                }
                duplicateItems.Add(cItem);
            }
        }
        private bool IsValid(ItemDefinition itemDefintion) {
            if (!_configuration.Settings.LimitToStacksizes) {
                return true;
            }
            else if (_configuration.BlacklistedItems.Contains(itemDefintion.shortname)) {
                return false;
            }
            else if (_data.Items[itemDefintion.shortname] <= 0) {
                return false;
            }
            return true;
        }
        /// <summary>
        /// Validates all Loot Spawns found
        /// </summary>
        private void ModifyItemAmountRanges() {
            if (_configuration.Settings.ForceCustomLootTables && (_configuration.ExtraLoot.Enabled && _configuration.ExtraLoot.ForceCustomLootTables)) {
                Puts("Skipping modifying default loot tables...");
                return;
            }
            var lootSpawns = UnityEngine.Resources.FindObjectsOfTypeAll<LootSpawn>();
            foreach (var lootSpawn in lootSpawns) {
                if (lootSpawn?.items == null) {
                    PrintDebug("Loot spawn data is null");
                    continue;
                }
                ModifyItemAmountRange(lootSpawn);
            }
            if (_originItemAmountRange.Count > 0) {
                Puts($"Modified '{_originItemAmountRange.Count}' loot data item ranges out of a total of '{lootSpawns.Length}'...");
            }
        }
        /// <summary>
        /// Validates given item amount ranged array and modifies/removes items if needed
        /// </summary>
        /// <param name="origin"></param>
        private void ModifyItemAmountRange(LootSpawn origin) {
            var tempItemsToSpawn = Pool.GetList<ItemAmountRanged>();
            for (int i = 0; i < origin.items.Length; i++) {
                var itemRangeToSpawn = origin.items[i];
                if (!IsValid(itemRangeToSpawn.itemDef)) {
                    continue;
                }
                tempItemsToSpawn.Add(itemRangeToSpawn);
            }
            if (tempItemsToSpawn.Count != origin.items.Length) {
                _originItemAmountRange.Add(origin, origin.items.Clone() as ItemAmountRanged[]);
                origin.items = tempItemsToSpawn.ToArray();
                PrintDebug($"Modified loot data of '{origin.name}'...");
            }
            Pool.FreeList(ref tempItemsToSpawn);
        }
        /// <summary>
        /// Resets all initially stored loot spawns to their default item ranges
        /// </summary>
        private void RestoreItemAmountRanges() {
            foreach (var lootSpawn in _originItemAmountRange) {
                lootSpawn.Key.items = lootSpawn.Value;
            }
            Puts($"Restored '{_originItemAmountRange.Count}' loot data item ranges to default...");
        }
        /// <summary>
        /// Adds default loot to the container
        /// </summary>
        /// <param name="container"></param>
        /// <param name="containerData"></param>
        private void AddDefaultLoot(LootContainer container, ContainerData containerData) {
            var useDefaultLootTables = !(containerData.Enabled && !containerData.VanillaLootTablesDefault);
            if (useDefaultLootTables) {
                useDefaultLootTables = !_configuration.Settings.ForceCustomLootTables;
            }
            if (container.LootSpawnSlots.Length != 0) {
                for (int i = 0; i < container.LootSpawnSlots.Length; i++) {
                    var lootSpawnSlot = container.LootSpawnSlots[i];
                    for (int j = 0; j < lootSpawnSlot.numberToSpawn; j++) {
                        if (UnityEngine.Random.Range(0f, 1f) <= lootSpawnSlot.probability) {
                            if (useDefaultLootTables) {
                                lootSpawnSlot.definition.SpawnIntoContainer(container.inventory);
                                continue;
                            }
                            AddRandomItem(container, containerData);
                        }
                    }
                }
            }
            else if (container.lootDefinition != null) {
                for (int k = 0; k < container.maxDefinitionsToSpawn; k++) {
                    if (useDefaultLootTables) {
                        container.lootDefinition.SpawnIntoContainer(container.inventory);
                        continue;
                    }
                    AddRandomItem(container, containerData);
                }
            }
        }
        /// <summary>
        /// Adds extra loot to the container, depending on both the Extra Loot and Specific Container Data
        /// </summary>
        /// <param name="container"></param>
        private void AddExtraLoot(LootContainer container, ContainerData containerData) {
            var useDefaultLootTables = !(containerData.Enabled && !containerData.VanillaLootTablesExtra);
            if (useDefaultLootTables) {
                useDefaultLootTables = !_configuration.ExtraLoot.ForceCustomLootTables;
            }
            var additionalItemsMin = 0;
            var additionalItemsMax = 0;
            if (_configuration.ExtraLoot.Enabled) {
                additionalItemsMin += _configuration.ExtraLoot.ExtraItemsMin;
                additionalItemsMax += _configuration.ExtraLoot.ExtraItemsMax;
            }
            if (containerData.Enabled) {
                additionalItemsMin += containerData.ExtraItemsMin;
                additionalItemsMax += containerData.ExtraItemsMax;
            }
            var additionalItems = UnityEngine.Random.Range(additionalItemsMin, additionalItemsMax + 1);
            for (int i = 0; i < additionalItems; i++) {
                if (useDefaultLootTables) {
                    AddRandomVanillaItem(container);
                }
                else {
                    AddRandomItem(container, containerData);
                }
            }
        }
        /// <summary>
        /// Adds a random Vanilla-LootTable Item to the Container
        /// </summary>
        /// <param name="container"></param>
        private void AddRandomVanillaItem(LootContainer container) {
            if (container.lootDefinition != null) {
                container.lootDefinition.SpawnIntoContainer(container.inventory);
            }
        }
        /// <summary>
        /// Adds a random Item to the Container
        /// </summary>
        /// <param name="container"></param>
        private void AddRandomItem(LootContainer container, ContainerData containerData) {
            if (containerData.Rarities.Count == 0) {
                PrintWarning("Using Non-Vanilla-LootTables but no set Rarity found in list for container : " + container.ShortPrefabName);
                containerData.Rarities.Add(Rarity.Common);
                SaveConfig();
            }
            var randomContainerRarity = Rarity.Common;
            if (containerData.RandomRarities && container.inventory.itemList.Count > 0) {
                randomContainerRarity = container.inventory.itemList[UnityEngine.Random.Range(0, container.inventory.itemList.Count)].info.rarity;
            }
            else {
                randomContainerRarity = containerData.Rarities[UnityEngine.Random.Range(0, containerData.Rarities.Count)];
            }
            var rarities = _sortedRarities[randomContainerRarity];
            var randomItemShortname = rarities[UnityEngine.Random.Range(0, rarities.Count)];
            var randomItem = ItemManager.itemDictionaryByName[randomItemShortname];
            if (_configuration.ExtraLoot.PreventDuplicates) {
                var duplicateItems = Pool.GetList<Item>();
                for (int i = 0; i < _configuration.ExtraLoot.PreventDuplicatesRetries; i++) {
                    FindDuplicates(randomItem.itemid, container.inventory.itemList, ref duplicateItems);
                    if (duplicateItems.Count > 0) {
                        randomItemShortname = rarities[UnityEngine.Random.Range(0, rarities.Count)];
                        randomItem = ItemManager.itemDictionaryByName[randomItemShortname];
                        duplicateItems.Clear();
                        if (i >= _configuration.ExtraLoot.PreventDuplicatesRetries - 1) {
                            PrintDebug("Unable to solve duplicate conflict with " + container.ShortPrefabName + " " + container.transform.position);
                        }
                    }
                    else {
                        break;
                    }
                }
                Pool.FreeList(ref duplicateItems);
            }
            var maxAmount = _data.Items[randomItemShortname];
            if (maxAmount > 0) {
                container.inventory.AddItem(randomItem, UnityEngine.Random.Range(1, maxAmount));
            }
        }
        /// <summary>
        /// Randomizes the durability of the Items in the Container if ROADSIDE or TOWN Container
        /// </summary>
        /// <param name="container"></param>
        private void RandomizeDurability(LootContainer container) {
            if (container.SpawnType == LootContainer.spawnType.ROADSIDE || container.SpawnType == LootContainer.spawnType.TOWN) {
                foreach (Item item in container.inventory.itemList) {
                    if (!item.hasCondition) {
                        continue;
                    }
                    item.condition = UnityEngine.Random.Range(item.info.condition.foundCondition.fractionMin, item.info.condition.foundCondition.fractionMax) * item.info.condition.max;
                }
            }
        }
        /// <summary>
        /// Generates a Rarity Dictionary containing only Item Definitions that are not Blacklisted
        /// </summary>
        /// <returns></returns>
        private Dictionary<Rarity, List<string>> GetSortedRarities() {
            var sortedRarities = new Dictionary<Rarity, List<string>>();
            foreach (var itemDef in ItemManager.itemList) {
                if (_configuration.BlacklistedItems.Contains(itemDef.shortname)) {
                    PrintDebug($"Filtering out '{itemDef.shortname}'");
                    continue;
                }
                if (_data.Items[itemDef.shortname] <= 0) {
                    continue;
                }
                if (!sortedRarities.ContainsKey(itemDef.rarity)) {
                    sortedRarities.Add(itemDef.rarity, new List<string>() {
                        itemDef.shortname
                    }
                    );
                    continue;
                }
                sortedRarities[itemDef.rarity].Add(itemDef.shortname);
            }
            Puts("Loaded Rarities...");
            return sortedRarities;
        }
        /// <summary>
        /// Returns if the container is NOT needed to be custom populated
        /// </summary>
        /// <param name="container"></param>
        /// <returns></returns>
        private bool IgnoreContainer(ContainerData containerData) {
            return !containerData.Enabled;
        }
        private ulong GetRandomSkin(ItemDefinition itemDef) {
            List<ulong> possibleSkins;
            if (_skinsCache.TryGetValue(itemDef.itemid, out possibleSkins)) {
                return possibleSkins[UnityEngine.Random.Range(0, possibleSkins.Count)];
            }
            possibleSkins = new List<ulong>() {
                0
            }
            ;
            foreach (var skin in ItemSkinDirectory.ForItem(itemDef)) {
                var skinId = (ulong)skin.id;
                if (_configuration.BlacklistSkins.Contains(skinId)) {
                    continue;
                }
                possibleSkins.Add(skinId);
            }
            foreach (var skin in Rust.Workshop.Approved.All.Values) {
                if (skin.Skinnable.ItemName != itemDef.shortname) {
                    continue;
                }
                if (_configuration.BlacklistSkins.Contains(skin.WorkshopdId)) {
                    continue;
                }
                possibleSkins.Add(skin.WorkshopdId);
            }
            _skinsCache.Add(itemDef.itemid, possibleSkins);
            return possibleSkins[UnityEngine.Random.Range(0, possibleSkins.Count)];
        }
        private void ApplySkinToItem(Item item, ulong skinId) {
            if (skinId == 0) {
                return;
            }
            item.skin = skinId;
            item.MarkDirty();
            BaseEntity heldEntity = item.GetHeldEntity();
            if (heldEntity != null) {
                heldEntity.skinID = skinId;
                heldEntity.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
            }
        }
        private void PrintDebug(object message) {
            if (!_configuration.Debug) {
                return;
            }
            Puts(message.ToString());
        }
#endregion
    }
}

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