using Oxide.Core; using Oxide.Core.Plugins; using System.Collections.Generic; using Newtonsoft.Json; namespace Oxide.Plugins { [Info("Loot Manager", "Corrosion", "1.0.0")] [Description("Visual loot table editor with profile switching")] public class LootManager : RustPlugin { #region Configuration private Configuration config; public class Configuration { [JsonProperty("Active Loot Profile")] public string ActiveProfile { get; set; } = "default"; [JsonProperty("Loot Profiles")] public Dictionary Profiles { get; set; } = new Dictionary(); } public class LootProfile { [JsonProperty("Profile Name")] public string Name { get; set; } [JsonProperty("Container Multipliers")] public Dictionary ContainerMultipliers { get; set; } = new Dictionary(); [JsonProperty("Custom Loot Tables")] public Dictionary> CustomLootTables { get; set; } = new Dictionary>(); } public class LootItem { [JsonProperty("Item Shortname")] public string Shortname { get; set; } [JsonProperty("Min Amount")] public int MinAmount { get; set; } [JsonProperty("Max Amount")] public int MaxAmount { get; set; } [JsonProperty("Spawn Chance")] public float SpawnChance { get; set; } [JsonProperty("Skin ID")] public ulong SkinId { get; set; } } protected override void LoadDefaultConfig() { config = new Configuration(); SaveConfig(); } protected override void LoadConfig() { base.LoadConfig(); config = Config.ReadObject(); SaveConfig(); } protected override void SaveConfig() => Config.WriteObject(config); #endregion #region Hooks void OnLootSpawn(LootContainer container) { // Apply active loot profile to this container if (config.Profiles.TryGetValue(config.ActiveProfile, out var profile)) { ModifyContainerLoot(container, profile); } } void OnEntitySpawned(BaseEntity entity) { // Handle barrel, crate, NPC loot spawns if (entity is LootContainer) { var container = entity as LootContainer; NextTick(() => OnLootSpawn(container)); } } #endregion #region Loot Modification private void ModifyContainerLoot(LootContainer container, LootProfile profile) { // Get container type (crate, barrel, elite, military, etc.) string containerType = GetContainerType(container); // Check if this container type has custom loot table if (profile.CustomLootTables.TryGetValue(containerType, out var lootTable)) { // Clear existing loot container.inventory.Clear(); // Populate with custom loot foreach (var lootItem in lootTable) { if (UnityEngine.Random.value <= lootItem.SpawnChance) { int amount = UnityEngine.Random.Range(lootItem.MinAmount, lootItem.MaxAmount + 1); var item = ItemManager.CreateByName(lootItem.Shortname, amount, lootItem.SkinId); if (item != null) { item.MoveToContainer(container.inventory); } } } } // Apply multiplier if no custom table else if (profile.ContainerMultipliers.TryGetValue(containerType, out var multiplier)) { foreach (var item in container.inventory.itemList) { item.amount = (int)(item.amount * multiplier); } } } private string GetContainerType(LootContainer container) { // Map container prefab to type string string prefab = container.ShortPrefabName.ToLower(); if (prefab.Contains("crate_normal")) return "normal_crate"; if (prefab.Contains("crate_elite")) return "elite_crate"; if (prefab.Contains("crate_mine")) return "mine_crate"; if (prefab.Contains("barrel")) return "barrel"; if (prefab.Contains("foodbox")) return "food_crate"; if (prefab.Contains("military")) return "military_crate"; return "default"; } #endregion #region Commands [ChatCommand("loot.profile")] private void CmdSwitchProfile(BasePlayer player, string command, string[] args) { if (!player.IsAdmin) return; if (args.Length == 0) { player.ChatMessage($"Current profile: {config.ActiveProfile}"); player.ChatMessage($"Available profiles: {string.Join(", ", config.Profiles.Keys)}"); return; } string profileName = args[0]; if (config.Profiles.ContainsKey(profileName)) { config.ActiveProfile = profileName; SaveConfig(); player.ChatMessage($"Switched to loot profile: {profileName}"); } else { player.ChatMessage($"Profile '{profileName}' not found."); } } #endregion } }