今天给大家分享一个rust腐蚀插件,就是魔法战利品(MagicLoot.cs),这个一般服务器都会有送,如果没有,那么自己下载安装即可。
主要功能:修改调节rust资源倍率,比如废料、木材、石材等资源的爆率。
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
}
}
© 版权声明
THE END
暂无评论内容