using System; using Oxide.Core; using System.Collections.Generic; using Newtonsoft.Json; using Oxide.Core.Configuration; using UnityEngine; using System.Linq; using Oxide.Core.Libraries.Covalence; using Oxide.Game.Rust.Libraries; namespace Oxide.Plugins { [Info("SimpleLootTable", "Fruster", "1.0.4")] [Description("SimpleLootTable")] class SimpleLootTable : CovalencePlugin { public class SimpleLootTableItem { public string itemName { get; set; } public string displayName { get; set; } public ulong skinID { get; set; } public float dropChance { get; set; } public int minAmount { get; set; } public int maxAmount { get; set; } } public class SimpleLootTableList { public string name { get; set; } public List table { get; set; } } public class SimpleLootTableUse { public string entityPrefabName { get; set; } public string tableName { get; set; } public int minItems { get; set; } public int maxItems { get; set; } public float multiplier { get; set; } } private DynamicConfigFile exampleTable = Interface.Oxide.DataFileSystem.GetDatafile("SimpleLootTable/exampleTable"); private List itemsList = new List(); private List tablesList = new List(); private List tablesNamesList = new(); private List containersList = new(); private ConfigData Configuration; class ConfigData { [JsonProperty("Use tables for entities")] public List tables = new List() { new SimpleLootTableUse{entityPrefabName = "loot_barrel_1", tableName = "", minItems = 2, maxItems = 5, multiplier = 1}, new SimpleLootTableUse{entityPrefabName = "loot_barrel_2", tableName = "", minItems = 2, maxItems = 5, multiplier = 1} }; } void SaveConfig(object config) => Config.WriteObject(config, true); void LoadConfig() { base.Config.Settings.ObjectCreationHandling = ObjectCreationHandling.Replace; Configuration = Config.ReadObject(); SaveConfig(Configuration); } protected override void LoadDefaultConfig() { Configuration = new ConfigData(); SaveConfig(); } private void Init() { Unsubscribe("OnEntitySpawned"); Unsubscribe("OnEntityKill"); LoadConfig(); CreateDefaultTable(); LoadAllTables(); tablesNamesList.AddRange(Configuration.tables.Where(table => !string.IsNullOrEmpty(table.tableName)).Select(table => table.entityPrefabName)); if (tablesNamesList.Any()) { Subscribe("OnEntitySpawned"); Subscribe("OnEntityKill"); foreach (var container in BaseNetworkable.serverEntities.OfType()) { var matchingTable = Configuration.tables.FirstOrDefault(table => table.entityPrefabName == container.PrefabName && !string.IsNullOrEmpty(table.tableName)); if (matchingTable != null && !containersList.Contains(container)) containersList.Add(container); } } } private void OnEntitySpawned(LootContainer container) { if (!tablesNamesList.Contains(container.PrefabName)) return; if (!containersList.Contains(container)) containersList.Add(container); var matchingTable = Configuration.tables.FirstOrDefault(table => table.entityPrefabName == container.PrefabName && !string.IsNullOrEmpty(table.tableName)); if (matchingTable != null) timer.Once(0.5f, () => { if (container == null || container.IsDestroyed) return; GetSetItems(container as BaseEntity, matchingTable.tableName, matchingTable.minItems, matchingTable.maxItems, matchingTable.multiplier); }); } private void OnEntityKill(LootContainer container) { if (containersList.Contains(container)) containersList.Remove(container); } private void CreateDefaultTable() { if (exampleTable["0"] == null) { itemsList.Add(new SimpleLootTableItem { itemName = "scrap", displayName = "", skinID = 0, dropChance = 100, minAmount = 50, maxAmount = 100 }); itemsList.Add(new SimpleLootTableItem { itemName = "blueberries", displayName = "", skinID = 0, dropChance = 90, minAmount = 3, maxAmount = 10 }); itemsList.Add(new SimpleLootTableItem { itemName = "ammo.rifle", displayName = "", skinID = 0, dropChance = 80, minAmount = 64, maxAmount = 128 }); itemsList.Add(new SimpleLootTableItem { itemName = "ammo.rifle.explosive", displayName = "", skinID = 0, dropChance = 50, minAmount = 64, maxAmount = 128 }); itemsList.Add(new SimpleLootTableItem { itemName = "ammo.pistol", displayName = "", skinID = 0, dropChance = 80, minAmount = 64, maxAmount = 128 }); itemsList.Add(new SimpleLootTableItem { itemName = "techparts", displayName = "", skinID = 0, dropChance = 40, minAmount = 1, maxAmount = 3 }); itemsList.Add(new SimpleLootTableItem { itemName = "riflebody", displayName = "", skinID = 0, dropChance = 40, minAmount = 1, maxAmount = 3 }); itemsList.Add(new SimpleLootTableItem { itemName = "semibody", displayName = "", skinID = 0, dropChance = 50, minAmount = 2, maxAmount = 4 }); itemsList.Add(new SimpleLootTableItem { itemName = "explosives", displayName = "", skinID = 0, dropChance = 50, minAmount = 10, maxAmount = 50 }); itemsList.Add(new SimpleLootTableItem { itemName = "explosive.satchel", displayName = "", skinID = 0, dropChance = 30, minAmount = 2, maxAmount = 5 }); itemsList.Add(new SimpleLootTableItem { itemName = "explosive.timed", displayName = "", skinID = 0, dropChance = 10, minAmount = 1, maxAmount = 2 }); itemsList.Add(new SimpleLootTableItem { itemName = "ammo.rocket.basic", displayName = "", skinID = 0, dropChance = 20, minAmount = 2, maxAmount = 4 }); itemsList.Add(new SimpleLootTableItem { itemName = "metal.facemask", displayName = "", skinID = 0, dropChance = 10, minAmount = 1, maxAmount = 1 }); itemsList.Add(new SimpleLootTableItem { itemName = "metal.plate.torso", displayName = "", skinID = 0, dropChance = 10, minAmount = 1, maxAmount = 1 }); itemsList.Add(new SimpleLootTableItem { itemName = "metalpipe", displayName = "", skinID = 0, dropChance = 80, minAmount = 2, maxAmount = 6 }); itemsList.Add(new SimpleLootTableItem { itemName = "metalspring", displayName = "", skinID = 0, dropChance = 80, minAmount = 2, maxAmount = 5 }); itemsList.Add(new SimpleLootTableItem { itemName = "rope", displayName = "", skinID = 0, dropChance = 80, minAmount = 2, maxAmount = 6 }); itemsList.Add(new SimpleLootTableItem { itemName = "smgbody", displayName = "", skinID = 0, dropChance = 40, minAmount = 2, maxAmount = 3 }); itemsList.Add(new SimpleLootTableItem { itemName = "sulfur", displayName = "", skinID = 0, dropChance = 60, minAmount = 1000, maxAmount = 3000 }); itemsList.Add(new SimpleLootTableItem { itemName = "rifle.ak", displayName = "Top gun", skinID = 809190373, dropChance = 5, minAmount = 1, maxAmount = 1 }); exampleTable.Clear(); for (int i = 0; i < itemsList.Count; i++) { exampleTable[i.ToString(), "itemName"] = itemsList[i].itemName; exampleTable[i.ToString(), "displayName"] = itemsList[i].displayName; exampleTable[i.ToString(), "skinID"] = itemsList[i].skinID; exampleTable[i.ToString(), "dropChance"] = itemsList[i].dropChance; exampleTable[i.ToString(), "minAmount"] = itemsList[i].minAmount; exampleTable[i.ToString(), "maxAmount"] = itemsList[i].maxAmount; } exampleTable.Save(); } } private void LoadAllTables() { DynamicConfigFile newFile; SimpleLootTableItem newItem; SimpleLootTableList newTableList; string[] filesList = Interface.Oxide.DataFileSystem.GetFiles("SimpleLootTable"); for (int i = 0; i < filesList.Length; i++) { newTableList = new SimpleLootTableList { name = filesList[i], table = new List() }; newFile = Interface.Oxide.DataFileSystem.GetDatafile(filesList[i].ToString().Replace(".json", "")); foreach (var item in newFile) { newItem = new SimpleLootTableItem { itemName = newFile[item.Key.ToString(), "itemName"].ToString(), displayName = newFile[item.Key.ToString(), "displayName"].ToString(), skinID = Convert.ToUInt32(newFile[item.Key.ToString(), "skinID"]), dropChance = Convert.ToSingle(newFile[item.Key.ToString(), "dropChance"]), minAmount = (int)newFile[item.Key.ToString(), "minAmount"], maxAmount = (int)newFile[item.Key.ToString(), "maxAmount"], }; newTableList.table.Add(newItem); } tablesList.Add(newTableList); } } private void GiveItem(StorageContainer container, string itemName, string displayName, int min, int max, ulong skinID, float multiplier) { int amount = Mathf.Max(1, (int)(UnityEngine.Random.Range(min, max) * multiplier)); Item item = ItemManager.CreateByName(itemName, amount, skinID); if (item == null) { PrintWarning($"In the config file there is an error in the name of the item - {itemName}!"); return; } if (!string.IsNullOrEmpty(displayName)) item.name = displayName; item.MoveToContainer(container.inventory); } private void GiveItemCorpse(ItemContainer container, string itemName, string displayName, int min, int max, ulong skinID, float multiplier) { int amount = Mathf.Max(1, (int)(UnityEngine.Random.Range(min, max) * multiplier)); Item item = ItemManager.CreateByName(itemName, amount, skinID); if (item == null) { PrintWarning($"In the config file there is an error in the name of the item - {itemName}!"); return; } if (!string.IsNullOrEmpty(displayName)) item.name = displayName; item.MoveToContainer(container); } private void GetSetItems(BaseEntity entity, string tableName, int minAmount, int maxAmount, float multiplier, bool clear = true) { if (!entity) return; StorageContainer container = entity.GetComponent(); ItemContainer corpseContainer = null; LootableCorpse lootableCorpse = entity.GetComponentInParent(); if (lootableCorpse) corpseContainer = lootableCorpse.containers[0]; if (!container && corpseContainer == null) { PrintWarning("Components 'StorageContainer' or 'ItemContainer' not found"); return; } int amount = UnityEngine.Random.Range(minAmount, maxAmount + 1); int index; float chance; List selectedItems = new List(); List tempList = new List(); List doneList = new List(); SimpleLootTableList table = tablesList.Find(item => item.name.Contains(tableName + ".json")); if (container) { if (container is HackableLockedCrate crate) crate.inventory.onItemAddedRemoved = null; if (clear) container.inventory.Clear(); if (container.inventory.capacity < maxAmount) container.inventory.capacity = maxAmount; } if (corpseContainer != null) { if (clear) corpseContainer.Clear(); if (corpseContainer.capacity < maxAmount) corpseContainer.capacity = maxAmount; } if (table != null) selectedItems = table.table; else { PrintWarning("No table found with name '" + tableName + "'!"); return; } for (int i = 0; i < selectedItems.Count; i++) tempList.Add(selectedItems[i]); for (int i = 0; i < selectedItems.Count; i++) if (selectedItems[i].dropChance >= 100) { if (amount < 1) { PrintWarning("The number of items with a 100% drop chance exceeds the maximum number of slots!"); break; } amount--; if (corpseContainer != null) GiveItemCorpse(corpseContainer, selectedItems[i].itemName, selectedItems[i].displayName, selectedItems[i].minAmount, selectedItems[i].maxAmount + 1, selectedItems[i].skinID, multiplier); else GiveItem(container, selectedItems[i].itemName, selectedItems[i].displayName, selectedItems[i].minAmount, selectedItems[i].maxAmount + 1, selectedItems[i].skinID, multiplier); doneList.Add(selectedItems[i]); tempList.Remove(selectedItems[i]); } while (amount > 0) { if (tempList.Count == 0) { amount = 0; break; } index = UnityEngine.Random.Range(0, tempList.Count); chance = UnityEngine.Random.Range(0f, 100f); if (chance < tempList[index].dropChance) { amount--; if (corpseContainer != null) GiveItemCorpse(corpseContainer, tempList[index].itemName, tempList[index].displayName, tempList[index].minAmount, tempList[index].maxAmount + 1, tempList[index].skinID, multiplier); else GiveItem(container, tempList[index].itemName, tempList[index].displayName, tempList[index].minAmount, tempList[index].maxAmount + 1, tempList[index].skinID, multiplier); tempList.Remove(tempList[index]); } } } [Command("simplt_refresh")] private void simplt_refresh(IPlayer iplayer) { if (iplayer.IsAdmin) foreach (var container in containersList) OnEntitySpawned(container); } } }