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

FREE AdvancedItemCrafting : 1.0.10 1.0.10

Нет прав для скачивания
C#:
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
using Facepunch;
/**
 * This plugin will not do anything standalone.
 * 
 * You need latest Epic Items or Item Perks installed.
 * - configurations for epic buffs are maintained in Epic Items
 * - epic buff effects are handled by Epic Items
 * - configurations for perk buffs are maintained in Item Perks
 * - perk buff effects are handled by Item Perks
 * - most translations are used from Epic Items and Item Perks to make transformation easier
 * 
 * TODOs by priority:
 * - remove inconsitencies when using CuiPanel etc
 * - revise UI component names and coords
 * 
 * possible Features/Ideas
 * - support for Item Retriever
 * - support for economics and stuff -> might be needed by some servers (even when i dont like it^^)
 * - Crafting XP -> used to unlock features?
 * - Admin Inventory Inspector -> to look into players inventory and validate items
 * - dont show costs if permission "free" is assigned -> maybe alternate text?
 **/
namespace Oxide.Plugins {
    [Info("AdvancedItemCrafting", "molokatan", "1.0.10"), Description("User Interface and advanced crafting options for Item Perks and Epic Loot")]
    class AdvancedItemCrafting : RustPlugin {
        [PluginReference]
        private Plugin EpicLoot, ItemPerks, ImageLibrary;
        // permissions for perk crafting
        const string perm_perk_add = "advanceditemcrafting.perk.add";
        const string perm_perk_remove = "advanceditemcrafting.perk.remove";
        const string perm_perk_randomize = "advanceditemcrafting.perk.randomize";
        // permission to bypass weight system
        const string perm_perk_bypass_weighting = "advanceditemcrafting.perk.bypass_weighting";
        const string perm_named_unveil = "advanceditemcrafting.named.unveil";
        // amount usable kits for perk crafts if weighted
        const string perm_kit_2 = "advanceditemcrafting.perk.kit2";
        const string perm_kit_3 = "advanceditemcrafting.perk.kit3";
        // permissions for epic items
        const string perm_salvage = "advanceditemcrafting.epic.salvage";
        const string perm_enhance = "advanceditemcrafting.epic.enhance";
        // FIXME: need to check behavior for kits
        const string perm_enhance_free = "advanceditemcrafting.free";
        const string perm_settings_hide_button = "advanceditemcrafting.settings.hide_button";
        // FIXME: this instance should be removed if possible
        public static AdvancedItemCrafting Instance {
            get;
            set;
        }
#region Hooks
        string btn_icon = "assets/icons/inventory.png";
        void OnServerInitialized() {
            Instance = this;
            if (config.user_experience.main_button.Enabled && !string.IsNullOrEmpty(config.user_experience.main_button.Icon)) {
                if (config.user_experience.main_button.Icon.StartsWith("http")) {
                    if (ImageLibrary == null || !ImageLibrary.IsLoaded) {
                        Puts("Image Library has to be installed to support web images");
                        Interface.Oxide.UnloadPlugin(Name);
                        return;
                    }
                    else {
                        ImageLibrary?.Call("AddImage", config.user_experience.main_button.Icon, "ai_btn_img");
                    }
                }
                btn_icon = config.user_experience.main_button.Icon;
            }
            if (EpicLoot == null || !EpicLoot.IsLoaded) {
                Puts("You must have Epic Loot installed to run this features.");
                // Interface.Oxide.UnloadPlugin(Name);
            }
            else {
                LoadEpicConfiguration();
            }
            if (ItemPerks == null || !ItemPerks.IsLoaded) {
                Puts("You must have Item Perks installed to run this features.");
                // Interface.Oxide.UnloadPlugin(Name);
            }
            else {
                LoadItemPerksConfiguration();
            }
            RegisterPermissions();
            if (BasePlayer.activePlayerList != null && config.user_experience.main_button.Enabled) {
                foreach (var player in BasePlayer.activePlayerList) CreateMainButton(player);
            }
            if (!string.IsNullOrEmpty(config.chatCmd)) cmd.AddChatCommand(config.chatCmd, this, "ChatOpenInventory");
        }
        void OnPlayerDeath(BasePlayer player) {
            CuiHelper.DestroyUi(player, MAIN_BUTTON);
            CuiHelper.DestroyUi(player, BACKDROP_PANEL);
        }
        void OnPlayerRespawned(BasePlayer player) {
            CreateMainButton(player);
        }
        void OnPlayerSleepEnded(BasePlayer player) {
            CreateMainButton(player);
        }
        void Unload() {
            foreach (var player in BasePlayer.activePlayerList) {
                CuiHelper.DestroyUi(player, MAIN_BUTTON);
                CuiHelper.DestroyUi(player, BACKDROP_PANEL);
            }
            if (!string.IsNullOrEmpty(config.chatCmd)) cmd.RemoveChatCommand(config.chatCmd, this);
        }
#endregion Hooks
#region Permissions
        void RegisterPermissions() {
            permission.RegisterPermission(perm_perk_add, this);
            permission.RegisterPermission(perm_perk_remove, this);
            permission.RegisterPermission(perm_perk_randomize, this);
            permission.RegisterPermission(perm_perk_bypass_weighting, this);
            permission.RegisterPermission(perm_named_unveil, this);
            permission.RegisterPermission(perm_kit_2, this);
            permission.RegisterPermission(perm_kit_3, this);
            permission.RegisterPermission(perm_salvage, this);
            permission.RegisterPermission(perm_enhance, this);
            permission.RegisterPermission(perm_enhance_free, this);
            permission.RegisterPermission(perm_settings_hide_button, this);
        }
        int GetMaxKits(BasePlayer player) {
            if (permission.UserHasPermission(player.UserIDString, perm_kit_3)) return 3;
            if (permission.UserHasPermission(player.UserIDString, perm_kit_2)) return 2;
            return 1;
        }
#endregion Permissions
#region Commands
#region Commands:Inventory
        void ChatOpenInventory(BasePlayer player) {
            if (player == null) return;
            var playerState = new PlayerState(player);
            var builder = new ExtendedCuiElementContainer();
            CreateInventoryBase(builder, player);
            CreateInventoryItems(builder, playerState);
            AddPlayerBuffsPanel(builder, player, playerState);
            CuiHelper.AddUi(player, builder);
        }
        [ConsoleCommand("cmdopeninventory")]
        void CmdOpenInventory(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            ChatOpenInventory(player);
        }
        [ConsoleCommand("cmdcloseinventory")]
        void CmdCloseInventory(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            CuiHelper.DestroyUi(player, BACKDROP_PANEL);
        }
#endregion Commands:Inventory
#region Commands:Settings
        [ConsoleCommand("cmdopenaisettings")]
        void CmdOpenSettings(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            var builder = new ExtendedCuiElementContainer();
            CreateSettingsBox(builder, player);
            CuiHelper.AddUi(player, builder);
        }
        [ConsoleCommand("cmdcloseaisettings")]
        void CmdCloseSettings(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            CuiHelper.DestroyUi(player, "AI_SETTINGS_BOX");
        }
        [ConsoleCommand("cmdtoggleaisetting")]
        void CmdToggleSettings(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            string setting = arg.GetString(0);
            switch (setting) {
                case "mainbutton" : TogglePermission(player, perm_settings_hide_button);
                CreateMainButton(player);
                break;
                // might add more settings later
            }
            var playerState = new PlayerState(player);
            var builder = new ExtendedCuiElementContainer();
            CreateInventoryBase(builder, player);
            CreateInventoryItems(builder, playerState);
            AddPlayerBuffsPanel(builder, player, playerState);
            CreateSettingsBox(builder, player);
            CuiHelper.AddUi(player, builder);
        }
        private void TogglePermission(BasePlayer player, string perm) {
            if (permission.UserHasPermission(player.UserIDString, perm)) permission.RevokeUserPermission(player.UserIDString, perm);
            else permission.GrantUserPermission(player.UserIDString, perm, null);
        }
#endregion Commands:Settings
        [ConsoleCommand("cmdselectitem")]
        void CmdSelectItem(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            uint selectedItemUID = arg.GetUInt(0);
            var item = player.inventory.FindItemByUID(new ItemId(selectedItemUID));
            if (item == null) return;
            var baseItem = new BaseItem(item);
            var builder = new ExtendedCuiElementContainer();
            CreateItemDetailsBase(builder, player, baseItem);
            CreateItemActions(builder, player, baseItem);
            AddEpicBuffDetailsPanel(builder);
            if (baseItem.buff != null && EpicLoot != null) {
                EpicBuffDescription(builder, player, baseItem.buff.Buff);
            }
            HighlightSelectedItem(builder, baseItem);
            CuiHelper.AddUi(player, builder);
        }
        [ConsoleCommand("cmdcloseinfobox")]
        void CmdCloseInfoBox(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            CuiHelper.DestroyUi(player, "AI_INFO_BOX");
        }
#region Commands:Epic
        [ConsoleCommand("cmdshowepicbuffselection")]
        void CmdShowEpicBuffSelection(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            uint selectedItemUID = arg.GetUInt(0);
            var item = player.inventory.FindItemByUID(new ItemId(selectedItemUID));
            if (item == null) return;
            var selectedBuff = Buff.None;
            if (!Enum.TryParse(arg.GetString(1), out selectedBuff)) return;
            var opened = arg.GetBool(2);
            var baseItem = new BaseItem(item);
            var builder = new ExtendedCuiElementContainer();
            AddEpicBuffDetailsPanel(builder);
            AddEpicBuffSelector(builder, player, baseItem, selectedBuff, opened);
            if (!opened) {
                int cost;
                if(selectedBuff == Buff.None || !epicConfig.scrapper_settings.enhancement_cost.TryGetValue(selectedBuff, out cost)) cost = 0;
                var hasPayment = ItemAmountAvailable(player, epicConfig.scrapper_settings.currency_shortname, epicConfig.scrapper_settings.currency_skin, epicConfig.scrapper_settings.currency_name);
                EpicBuffDescription(builder, player, selectedBuff);
                AddEpicBuffConfirmPanel(builder, player, baseItem, selectedBuff, hasPayment >= cost);
            }
            CuiHelper.AddUi(player, builder);
        }
        [ConsoleCommand("cmdconfirmepicselection")]
        void CmdConfirmEpicSelection(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            CuiHelper.DestroyUi(player, EPIC_BUFF_DETAILS_PANEL);
            var selectedItemUID = arg.GetUInt64(0);
            var itemToEnhance = player.inventory.FindItemByUID(new ItemId(selectedItemUID));
            if (itemToEnhance == null) return;
            var selectedBuff = Buff.None;
            if (!Enum.TryParse(arg.GetString(1), out selectedBuff)) return;
            int cost;
            if(selectedBuff == Buff.None || !epicConfig.scrapper_settings.enhancement_cost.TryGetValue(selectedBuff, out cost)) return;
            // FIXME: show an error message if it did not work?
            if (!PayItems(player, epicConfig.scrapper_settings.currency_shortname, epicConfig.scrapper_settings.currency_skin, epicConfig.scrapper_settings.currency_name, cost)) return;
            // we want to make sure only 1 item gets the epic buff
            if (itemToEnhance.amount > 1) itemToEnhance = itemToEnhance.SplitItem(1);
            EpicLoot?.Call<string>("GenerateItem", player, selectedBuff.ToString(), new List<string> {
                itemToEnhance.info.shortname
            }
            , null, true, itemToEnhance);
            itemToEnhance.SetItemOwnership(lang.GetMessage("OWNERSHIP_TAG_EPIC", this), GetOwnershipHeader(player));
            // refeshing inventory to remove payments and show the new item
            var playerState = new PlayerState(player);
            var baseItem = new BaseItem(itemToEnhance);
            var builder = new ExtendedCuiElementContainer();
            CreateInventoryBase(builder, player);
            CreateInventoryItems(builder, playerState);
            AddPlayerBuffsPanel(builder, player, playerState);
            CreateItemDetailsBase(builder, player, baseItem);
            CreateItemActions(builder, player, baseItem);
            AddEpicBuffDetailsPanel(builder);
            EpicBuffDescription(builder, player, baseItem.buff.Buff);
            HighlightSelectedItem(builder, baseItem);
            CuiHelper.AddUi(player, builder);
        }
        [ConsoleCommand("cmdcancelepicselection")]
        void CmdCancelEpicSelection(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            CuiHelper.DestroyUi(player, EPIC_BUFF_DETAILS_PANEL);
        }
        [ConsoleCommand("cmdsalvageepicitem")]
        void CmdSalvageEpicItem(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            var selectedItemUID = arg.GetUInt64(0);
            var itemToSalvage = player.inventory.FindItemByUID(new ItemId(selectedItemUID));
            if (itemToSalvage == null) return;
            var baseItem = new BaseItem(itemToSalvage);
            int amount;
            if (!epicConfig.scrapper_settings.scrapper_value.TryGetValue(baseItem.buff.Tier, out amount)) return;
            if (itemToSalvage.amount > 1) itemToSalvage = itemToSalvage.SplitItem(1);
            itemToSalvage.RemoveFromContainer();
            var payment = ItemManager.CreateByName(epicConfig.scrapper_settings.currency_shortname, Math.Max(amount, 1), epicConfig.scrapper_settings.currency_skin);
            if (payment == null) return;
            if (!string.IsNullOrEmpty(epicConfig.scrapper_settings.currency_name)) payment.name = epicConfig.scrapper_settings.currency_name;
            player.GiveItem(payment);
            NextTick(() => itemToSalvage.Remove());
            // refeshing inventory to remove item and add currency
            var playerState = new PlayerState(player);
            var builder = new ExtendedCuiElementContainer();
            CreateInventoryBase(builder, player);
            CreateInventoryItems(builder, playerState);
            AddPlayerBuffsPanel(builder, player, playerState);
            CuiHelper.AddUi(player, builder);
        }
#endregion Commands:Epic
#region Commands:Perks
        // select kits that increase chance for actions
        [ConsoleCommand("cmdselectperkbuffs")]
        void CmdSelectPerkBuffs(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            var selectedItemUID = arg.GetUInt64(0);
            var itemToMod = player.inventory.FindItemByUID(new ItemId(selectedItemUID));
            if (itemToMod == null) return;
            string action = arg.GetString(1);
            var selectedPerks = CLI.Deserialize<List<Perk>>(arg.GetString(2));
            BaseItem baseItem = new BaseItem(itemToMod);
            CraftItem craftItem = GetCraftItem(action);
            int additionalCost = GetCraftItemAmountRequired(craftItem, selectedPerks);
            bool hasPayment = craftItem != null ? CraftItemAmountAvailable(player, craftItem) >= additionalCost : true;
            bool isWeighted = IsWeightedAction(player, action);
            var maxKits = 1;
            if (isWeighted) maxKits = GetMaxKits(player);
            else if (action == "cmdrandomizeperkvalues" || action == "cmdunveilperk") maxKits = 0;
            string headerText = lang.GetMessage(action.ToUpper() + "_HEADER", this, player.UserIDString);
            string infoMessageKey = $"{action.ToUpper()}_INFO{(maxKits > 1 ? "" : $"_ {
                maxKits
            }
            ")}";
            string infoText = string.Format(lang.GetMessage(infoMessageKey, this, player.UserIDString), maxKits) + (isWeighted ? "\n"+lang.GetMessage("CAN_FAIL", this, player.UserIDString) : "");
            ExtendedCuiElementContainer builder = new ExtendedCuiElementContainer();
            SelectPerkBuffsPanel(builder, player, headerText, infoText, baseItem, selectedPerks, maxKits, action, hasPayment);
            if (maxKits > 0) SelectKitPanel(builder, player, SELECT_PERK_BUFF_PANEL, 150, baseItem, selectedPerks, maxKits, action);
            if (craftItem != null && additionalCost > 0) AdditionalCostPanel(builder, player, SELECT_PERK_BUFF_PANEL, craftItem, additionalCost, hasPayment);
            CuiHelper.AddUi(player, builder);
        }
        [ConsoleCommand("cmdcloseselectperkbuffs")]
        void CmdCloseSelectPerkBuffs(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            // reload to make sure that inventory is updated
            var playerState = new PlayerState(player);
            var builder = new ExtendedCuiElementContainer();
            CreateInventoryBase(builder, player);
            CreateInventoryItems(builder, playerState);
            AddPlayerBuffsPanel(builder, player, playerState);
            if (arg.Args.Count() > 0) {
                var selectedItemUID = arg.GetUInt64(0);
                var itemToMod = player.inventory.FindItemByUID(new ItemId(selectedItemUID));
                var baseItem = new BaseItem(itemToMod);
                CreateItemDetailsBase(builder, player, baseItem);
                CreateItemActions(builder, player, baseItem);
                HighlightSelectedItem(builder, baseItem);
            }
            CuiHelper.AddUi(player, builder);
        }
        [ConsoleCommand("cmdunveilperk")]
        void CmdUnveilPerk(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            var selectedItemUID = arg.GetUInt64(0);
            var itemToMod = player.inventory.FindItemByUID(new ItemId(selectedItemUID));
            if (itemToMod == null) return;
            if (!UnveilPerk(player, itemToMod)) return;
            // refeshing inventory to remove payments
            var playerState = new PlayerState(player);
            var baseItem = new BaseItem(itemToMod);
            // FIXME: can we reuse open inventory & select item?
            var builder = new ExtendedCuiElementContainer();
            CreateInventoryBase(builder, player);
            CreateInventoryItems(builder, playerState);
            AddPlayerBuffsPanel(builder, player, playerState);
            CreateItemDetailsBase(builder, player, baseItem);
            CreateItemActions(builder, player, baseItem);
            HighlightSelectedItem(builder, baseItem);
            CuiHelper.AddUi(player, builder);
        }
        [ConsoleCommand("cmdaddperk")]
        void CmdAddPerk(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            var selectedItemUID = arg.GetUInt64(0);
            var itemToMod = player.inventory.FindItemByUID(new ItemId(selectedItemUID));
            if (itemToMod == null) return;
            var selectedPerks = CLI.Deserialize<List<Perk>>(arg.GetString(1));
            if (IsWeightedAction(player, "cmdaddperk")) {
                if (!AddWeightedPerk(player, itemToMod, selectedPerks)) return;
            }
            else if (!AddUnweightedPerk(player, itemToMod, selectedPerks.First())) return;
            // refeshing inventory to remove payments
            var playerState = new PlayerState(player);
            var baseItem = new BaseItem(itemToMod);
            // FIXME: can we reuse open inventory & select item?
            var builder = new ExtendedCuiElementContainer();
            CreateInventoryBase(builder, player);
            CreateInventoryItems(builder, playerState);
            AddPlayerBuffsPanel(builder, player, playerState);
            CreateItemDetailsBase(builder, player, baseItem);
            CreateItemActions(builder, player, baseItem);
            HighlightSelectedItem(builder, baseItem);
            CuiHelper.AddUi(player, builder);
        }
        [ConsoleCommand("cmdrandomizeperkvalues")]
        void CmdRandomizePerkValues(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            var selectedItemUID = arg.GetUInt64(0);
            var itemToMod = player.inventory.FindItemByUID(new ItemId(selectedItemUID));
            if (itemToMod == null) return;
            var selectedPerks = CLI.Deserialize<List<Perk>>(arg.GetString(1));
            if (!RandomizePerkValues(player, itemToMod, selectedPerks)) return;
            // now we reopen the selection
            player.SendConsoleCommand("cmdselectperkbuffs", itemToMod.uid.Value, "cmdrandomizeperkvalues", CLI.Serialize(new List<Perk>()));
        }
        [ConsoleCommand("cmdremoveperk")]
        void CmdRemovePerk(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            var selectedItemUID = arg.GetUInt64(0);
            var itemToMod = player.inventory.FindItemByUID(new ItemId(selectedItemUID));
            if (itemToMod == null) return;
            var selectedPerks = CLI.Deserialize<List<Perk>>(arg.GetString(1));
            if (IsWeightedAction(player, "cmdremoveperk")) {
                if (!RemoveWeightedPerk(player, itemToMod, selectedPerks)) return;
            }
            else if (!RemoveUnweightedPerk(player, itemToMod, selectedPerks.First()));
            // refeshing inventory to remove payments
            var playerState = new PlayerState(player);
            var baseItem = new BaseItem(itemToMod);
            // FIXME: can we reuse open inventory & select item?
            var builder = new ExtendedCuiElementContainer();
            CreateInventoryBase(builder, player);
            CreateInventoryItems(builder, playerState);
            AddPlayerBuffsPanel(builder, player, playerState);
            CreateItemDetailsBase(builder, player, baseItem);
            CreateItemActions(builder, player, baseItem);
            CuiHelper.AddUi(player, builder);
        }
        [ConsoleCommand("cmdshowperkinfopanel")]
        void CmdShowPerkInfoPanel(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            var perk = Perk.None;
            if (!Enum.TryParse(arg.GetString(0), out perk)) return;
            var builder = new ExtendedCuiElementContainer();
            builder.AddInfoBox(lang.GetMessage("UI" + perk.ToString(), ItemPerks, player.UserIDString), GetPerkDescription(player, perk), lang.GetMessage("UI_OK", this, player.UserIDString));
            CuiHelper.AddUi(player, builder);
        }
#endregion Commands:Perks
#endregion Commands
#region Actions
#region Actions: Unveil
        public bool UnveilPerk(BasePlayer player, Item itemToMod) {
            BaseItem baseItem = new BaseItem(itemToMod);
            if (!CanUnveilPerkBuff(baseItem)) return false;
            CraftItem craftItem = config.craft_settings.unveil_perk_settings.craft_item;
            int additionalCost = GetCraftItemAmountRequired(craftItem);
            bool hasPayment = craftItem != null ? CraftItemAmountAvailable(player, craftItem) >= additionalCost : true;
            if (!hasPayment) return false;
            // if unrestricted, it will bypass white and blacklists, so we can unveil all perks -> makes them stronger
            var list = config.craft_settings.unveil_perk_settings.unrestricted ? GetEnabledPerkSettings() : GetAvailablePerkSettingsForItem(baseItem);
            if (list.Count == 0) return false;
            // we can guarantee that perks with 0 weight are used for those items
            var minWeight = config.craft_settings.unveil_perk_settings.min_weight_for_perks;
            var perkWeights = list .ToDictionary(el => el.Key, el => el.Value.perkWeight >= minWeight ? el.Value.perkWeight : minWeight);
            var totalWeight = perkWeights.Sum(a => a.Value);
            var weighthit = new System.Random().Next(totalWeight);
            Perk perkToAdd = Perk.None;
            foreach (var perkWeight in perkWeights) {
                weighthit -= perkWeight.Value;
                if (weighthit <= 0) {
                    perkToAdd = perkWeight.Key;
                    break;
                }
            }
            // FIXME: notify that adding perk failed -> NONE selected
            if (perkToAdd.Equals(Perk.None)) return false;
            PerkSettings perkMods;
            if (!perkConfig.enhancementSettings.perk_settings.TryGetValue(perkToAdd, out perkMods)) return false;
            float mod = (float)Math.Round(UnityEngine.Random.Range(perkMods.min_mod, perkMods.max_mod), 4);
            // get payment
            if (craftItem != null) if (!PayItems(player, craftItem.shortname, craftItem.skin, craftItem.display_name, additionalCost)) return false;
            baseItem.perks.Add(new PerkEntry {
                Perk = perkToAdd, Value = mod
            }
            );
            // recreate new perk string
            string perkString = "";
            foreach (var perk in baseItem.perks) {
                perkString += $"[{perk.Perk} {perk.Value}]";
            }
            if (baseItem.buff == null && string.IsNullOrEmpty(itemToMod.name)) {
                if (baseItem.named) itemToMod.name = baseItem.DisplayName;
                else itemToMod.name = $"{perkConfig.enhancementSettings.item_name_prefix} {itemToMod.info.displayName?.english}";
            }
            itemToMod.text = perkString;
            itemToMod.text += "[named]";
            itemToMod.SetItemOwnership(lang.GetMessage("OWNERSHIP_TAG_LEGENDARY", this), GetOwnershipHeader(player) + GetPerkOwnershipDescription(itemToMod));
            itemToMod.MarkDirty();
            if (config.craft_settings.unveil_perk_settings.success_effect != null) EffectNetwork.Send(new Effect(config.craft_settings.unveil_perk_settings.success_effect, player.transform.position, player.transform.position), player.net.connection);
            return true;
        }
#endregion
#region Actions: Perks
        public bool AddUnweightedPerk(BasePlayer player, Item itemToMod, Perk selectedPerk) {
            BaseItem baseItem = new BaseItem(itemToMod);
            if (!CanReceivePerkBuff(baseItem)) return false;
            CraftItem craftItem = config.craft_settings.add_perk_settings.craft_item;
            int additionalCost = GetCraftItemAmountRequired(craftItem, new List<Perk> {
                selectedPerk
            }
            );
            bool hasPayment = craftItem != null ? CraftItemAmountAvailable(player, craftItem) >= additionalCost : true;
            if (!hasPayment) return false;
            var requiredKits = GetRequiredKitAmount(new List<Perk> {
                selectedPerk
            }
            );
            if (!HasKits(player, requiredKits)) return false;
            PerkSettings perkMods;
            if (!perkConfig.enhancementSettings.perk_settings.TryGetValue(selectedPerk, out perkMods)) return false;
            if (!perkMods.enabled) return false;
            if (perkMods.blacklist != null && perkMods.blacklist.Count > 0 && perkMods.blacklist.Contains(baseItem.shortname)) return false;
            if (perkMods.whitelist != null && perkMods.whitelist.Count > 0 && !perkMods.whitelist.Contains(baseItem.shortname)) return false;
            float mod = (float)Math.Round(UnityEngine.Random.Range(perkMods.min_mod, perkMods.max_mod), 4);
            // get payment
            if (craftItem != null) if (!PayItems(player, craftItem.shortname, craftItem.skin, craftItem.display_name, additionalCost)) return false;
            if (!PayKits(player, requiredKits)) return false;
            baseItem.perks.Add(new PerkEntry {
                Perk = selectedPerk, Value = mod
            }
            );
            // recreate new perk string
            string perkString = "";
            foreach (var perk in baseItem.perks) {
                perkString += $"[{perk.Perk} {perk.Value}]";
            }
            // we want to make sure only 1 item gets the perk buff
            if (itemToMod.amount > 1) itemToMod = itemToMod.SplitItem(1);
            if (baseItem.buff == null && !string.IsNullOrEmpty(perkConfig.enhancementSettings.item_name_prefix) && string.IsNullOrEmpty(itemToMod.name)) itemToMod.name = $"{perkConfig.enhancementSettings.item_name_prefix} {itemToMod.info.displayName?.english}";
            itemToMod.text = perkString;
            itemToMod.SetItemOwnership(lang.GetMessage("OWNERSHIP_TAG_PERK", this), GetOwnershipHeader(player) + GetPerkOwnershipDescription(itemToMod));
            itemToMod.MarkDirty();
            return true;
        }
        public bool AddWeightedPerk(BasePlayer player, Item itemToMod, List<Perk> selectedPerks) {
            BaseItem baseItem = new BaseItem(itemToMod);
            if (!CanReceivePerkBuff(baseItem)) return false;
            CraftItem craftItem = config.craft_settings.add_perk_settings.craft_item;
            int additionalCost = GetCraftItemAmountRequired(craftItem, selectedPerks);
            bool hasPayment = craftItem != null ? CraftItemAmountAvailable(player, craftItem) >= additionalCost : true;
            if (!hasPayment) return false;
            var requiredKits = GetRequiredKitAmount(selectedPerks);
            if (!HasKits(player, requiredKits)) return false;
            var perkMultiplier = GetPerkMultiplier(selectedPerks.Count, "cmdaddperk");
            var perkWeights = GetAvailablePerkSettingsForItem(baseItem) .ToDictionary(el => el.Key, el => el.Value.perkWeight);
            // modify perk weights with selected kits
            foreach (var kit in requiredKits) perkWeights[kit.Key] += (int)(perkWeights[kit.Key] * requiredKits[kit.Key] * perkMultiplier);
            var totalWeight = perkWeights.Sum(a => a.Value);
            var weighthit = new System.Random().Next((totalWeight));
            Perk perkToAdd = Perk.None;
            foreach (var perkWeight in perkWeights) {
                weighthit -= perkWeight.Value;
                if (weighthit <= 0) {
                    perkToAdd = perkWeight.Key;
                    break;
                }
            }
            // FIXME: notify that adding perk failed -> NONE selected
            if (perkToAdd.Equals(Perk.None)) return false;
            PerkSettings perkMods;
            if (!perkConfig.enhancementSettings.perk_settings.TryGetValue(perkToAdd, out perkMods)) return false;
            float mod = (float)Math.Round(UnityEngine.Random.Range(perkMods.min_mod, perkMods.max_mod), 4);
            // get payment
            if (craftItem != null) if (!PayItems(player, craftItem.shortname, craftItem.skin, craftItem.display_name, additionalCost)) return false;
            if (!PayKits(player, requiredKits)) return false;
            baseItem.perks.Add(new PerkEntry {
                Perk = perkToAdd, Value = mod
            }
            );
            // recreate new perk string
            string perkString = "";
            foreach (var perk in baseItem.perks) {
                perkString += $"[{perk.Perk} {perk.Value}]";
            }
            // we want to make sure only 1 item gets the perk buff
            if (itemToMod.amount > 1) itemToMod = itemToMod.SplitItem(1);
            if (baseItem.buff == null && !string.IsNullOrEmpty(perkConfig.enhancementSettings.item_name_prefix) && string.IsNullOrEmpty(itemToMod.name)) itemToMod.name = $"{perkConfig.enhancementSettings.item_name_prefix} {itemToMod.info.displayName?.english}";
            itemToMod.text = perkString;
            itemToMod.SetItemOwnership(lang.GetMessage("OWNERSHIP_TAG_PERK", this), GetOwnershipHeader(player) + GetPerkOwnershipDescription(itemToMod));
            itemToMod.MarkDirty();
            if (config.craft_settings.add_perk_settings.weight_system.success_effect != null && (selectedPerks.Count == 0 || (selectedPerks.Count > 0 && selectedPerks.Contains(perkToAdd)))) EffectNetwork.Send(new Effect(config.craft_settings.add_perk_settings.weight_system.success_effect, player.transform.position, player.transform.position), player.net.connection);
            else if (config.craft_settings.add_perk_settings.weight_system.fail_effect != null && selectedPerks.Count > 0) EffectNetwork.Send(new Effect(config.craft_settings.add_perk_settings.weight_system.fail_effect, player.transform.position, player.transform.position), player.net.connection);
            return true;
        }
        public bool RemoveUnweightedPerk(BasePlayer player, Item itemToMod, Perk selectedPerk) {
            BaseItem baseItem = new BaseItem(itemToMod);
            if (!CanRemovePerkBuff(baseItem)) return false;
            CraftItem craftItem = config.craft_settings.remove_perk_settings.craft_item;
            int additionalCost = GetCraftItemAmountRequired(craftItem, new List<Perk> {
                selectedPerk
            }
            );
            bool hasPayment = craftItem != null ? CraftItemAmountAvailable(player, craftItem) >= additionalCost : true;
            if (!hasPayment) return false;
            var requiredKits = GetRequiredKitAmount(new List<Perk> {
                selectedPerk
            }
            );
            if (!HasKits(player, requiredKits)) return false;
            PerkSettings perkMods;
            if (!perkConfig.enhancementSettings.perk_settings.TryGetValue(selectedPerk, out perkMods)) return false;
            if (!perkMods.enabled) return false;
            var itemPerkKeys = baseItem.perks.Select(el => el.Perk);
            // FIXME: notify that removing perk failed -> NONE selected
            if (!itemPerkKeys.Contains(selectedPerk) || selectedPerk.Equals(Perk.None)) return false;
            // get payment
            if (craftItem != null) if (!PayItems(player, craftItem.shortname, craftItem.skin, craftItem.display_name, additionalCost)) return false;
            if (!PayKits(player, requiredKits)) return false;
            baseItem.perks.RemoveAt(baseItem.perks.FindIndex(i => i.Perk.Equals(selectedPerk)));
            // recreate new perk string
            string perkString = "";
            foreach (var perk in baseItem.perks) {
                perkString += $"[{perk.Perk} {perk.Value}]";
            }
            itemToMod.text = perkString;
            itemToMod.SetItemOwnership(lang.GetMessage("OWNERSHIP_TAG_PERK", this), GetOwnershipHeader(player) + GetPerkOwnershipDescription(itemToMod));
            itemToMod.MarkDirty();
            return true;
        }
        public bool RemoveWeightedPerk(BasePlayer player, Item itemToMod, List<Perk> selectedPerks) {
            BaseItem baseItem = new BaseItem(itemToMod);
            if (!CanRemovePerkBuff(baseItem)) return false;
            CraftItem craftItem = config.craft_settings.remove_perk_settings.craft_item;
            int additionalCost = GetCraftItemAmountRequired(craftItem, selectedPerks);
            bool hasPayment = craftItem != null ? CraftItemAmountAvailable(player, craftItem) >= additionalCost : true;
            if (!hasPayment) return false;
            var requiredKits = GetRequiredKitAmount(selectedPerks);
            if (!HasKits(player, requiredKits)) return false;
            var perkMultiplier = GetPerkMultiplier(selectedPerks.Count, "cmdremoveperk");
            var itemPerkKeys = baseItem.perks.Select(el => el.Perk);
            var perkWeights = GetAvailablePerkSettingsForItem(baseItem) .Where(el => itemPerkKeys.Contains(el.Key)) .ToDictionary(el => el.Key, el => el.Value.perkWeight);
            // modify perk weights with selected kits
            foreach (var kit in requiredKits) perkWeights[kit.Key] += (int)(perkWeights[kit.Key] * requiredKits[kit.Key] * perkMultiplier);
            var totalWeight = perkWeights.Sum(a => a.Value);
            var weighthit = new System.Random().Next((totalWeight));
            Perk perkToRemove = Perk.None;
            foreach (var perkWeight in perkWeights) {
                weighthit -= perkWeight.Value;
                if (weighthit <= 0) {
                    perkToRemove = perkWeight.Key;
                    break;
                }
            }
            // FIXME: notify that removing perk failed -> NONE selected
            if (perkToRemove.Equals(Perk.None)) return false;
            // get payment
            if (craftItem != null) if (!PayItems(player, craftItem.shortname, craftItem.skin, craftItem.display_name, additionalCost)) return false;
            if (!PayKits(player, requiredKits)) return false;
            baseItem.perks.RemoveAt(baseItem.perks.FindIndex(i => i.Perk.Equals(perkToRemove)));
            // recreate new perk string
            string perkString = "";
            foreach (var perk in baseItem.perks) {
                perkString += $"[{perk.Perk} {perk.Value}]";
            }
            itemToMod.text = perkString;
            itemToMod.SetItemOwnership(lang.GetMessage("OWNERSHIP_TAG_PERK", this), GetOwnershipHeader(player) + GetPerkOwnershipDescription(itemToMod));
            itemToMod.MarkDirty();
            if (config.craft_settings.remove_perk_settings.weight_system.success_effect != null && (selectedPerks.Count == 0 || (selectedPerks.Count > 0 && selectedPerks.Contains(perkToRemove)))) EffectNetwork.Send(new Effect(config.craft_settings.remove_perk_settings.weight_system.success_effect, player.transform.position, player.transform.position), player.net.connection);
            else if (config.craft_settings.remove_perk_settings.weight_system.fail_effect != null && selectedPerks.Count > 0) EffectNetwork.Send(new Effect(config.craft_settings.remove_perk_settings.weight_system.fail_effect, player.transform.position, player.transform.position), player.net.connection);
            return true;
        }
        public bool RandomizePerkValues(BasePlayer player, Item itemToMod, List<Perk> selectedPerks) {
            BaseItem baseItem = new BaseItem(itemToMod);
            if (baseItem.perks.Count < 1) return false;
            CraftItem craftItem = config.craft_settings.randomize_perk_settings.randomize_perk_item;
            int additionalCost = GetCraftItemAmountRequired(craftItem, selectedPerks);
            bool hasPayment = craftItem != null ? CraftItemAmountAvailable(player, craftItem) >= additionalCost : true;
            if (!hasPayment) return false;
            var requiredKits = GetRequiredKitAmount(selectedPerks);
            if (!HasKits(player, requiredKits)) return false;
            // get payment
            if (craftItem != null) if (!PayItems(player, craftItem.shortname, craftItem.skin, craftItem.display_name, additionalCost)) return false;
            if (!PayKits(player, requiredKits)) return false;
            string perkString = string.Empty;
            foreach (var entry in baseItem.perks) {
                PerkSettings perkMods;
                if (!perkConfig.enhancementSettings.perk_settings.TryGetValue(entry.Perk, out perkMods)) continue;
                double mod = perkMods.min_mod;
                int rollCount = 1;
                if (requiredKits.TryGetValue(entry.Perk, out int amount) && amount > 0) {
                    rollCount++;
                    requiredKits[entry.Perk]--;
                }
                ;
                for (int i = 0; i<rollCount; i++) {
                    var roll = Math.Round(UnityEngine.Random.Range(perkMods.min_mod, perkMods.max_mod), 4);
                    if (roll <= mod) continue;
                    mod = roll;
                }
                perkString += $"[{entry.Perk.ToString()} {mod}]";
            }
            itemToMod.text = perkString;
            itemToMod.SetItemOwnership(lang.GetMessage("OWNERSHIP_TAG_PERK", this), GetOwnershipHeader(player) + GetPerkOwnershipDescription(itemToMod));
            itemToMod.MarkDirty();
            if (config.craft_settings.randomize_perk_settings.success_effect != null) EffectNetwork.Send(new Effect(config.craft_settings.randomize_perk_settings.success_effect, player.transform.position, player.transform.position), player.net.connection);
            return true;
        }
        public string GetOwnershipHeader(BasePlayer player) => string.Format(lang.GetMessage("OWNERSHIP_DESCRIPTION_HEADER", this), lang.GetMessage("OWNERSHIP_CREATED", this), player?.displayName);
        public string GetPerkOwnershipDescription(Item item) {
            List<PerkEntry> perks = new BaseItem(item).perks;
            // FIXME: we want to keep the original creator of the item.
            string perkString = string.Empty;
            foreach(var perk in perks) {
                string perkName = lang.GetMessage("UI" + perk.Perk.ToString(), ItemPerks);
                perkString += string.Format(lang.GetMessage("OWNERSHIP_DESCRIPTION_PERK_LINE", this), perkName, GetPerkValue(perk.Value, perk.Perk), GetPerkTypeString(perk.Perk));
            }
            return string.Format(lang.GetMessage("OWNERSHIP_DESCRIPTION_PERKS", this), perkString);
        }
        public bool HasKits(BasePlayer player, Dictionary<Perk, int> requiredAmount) {
            if (requiredAmount.Count == 0) return true;
            foreach(var requiredPerk in requiredAmount) if (ItemAmountAvailable(player, perkConfig.enhancementSettings.enhancement_kit_settings.shortname, perkConfig.enhancementSettings.enhancement_kit_settings.skin, $"{perkConfig.enhancementSettings.enhancement_kit_settings.displayName} {requiredPerk.Key}") < requiredPerk.Value) return false;
            return true;
        }
        public Dictionary<Perk, int> GetRequiredKitAmount(List<Perk> selectedPerks) {
            Dictionary<Perk, int> requiredAmount = new Dictionary<Perk, int>();
            foreach(var perk in selectedPerks) {
                if (!requiredAmount.ContainsKey(perk)) requiredAmount.Add(perk, 1);
                else requiredAmount[perk]++;
            }
            return requiredAmount;
        }
        public float GetPerkMultiplier(int count, string action) {
            WeightRolls actionWeights = null;
            switch (action) {
                case "cmdaddperk" : actionWeights = config.craft_settings.add_perk_settings.weight_system;
                break;
                case "cmdremoveperk" : actionWeights = config.craft_settings.remove_perk_settings.weight_system;
                break;
                default : return 1f;
            }
            switch (count) {
                case 1 : return actionWeights.multiplier_1;
                case 2 : return actionWeights.multiplier_2;
                case 3 : return actionWeights.multiplier_3;
                default : return 1f;
            }
        }
        public Dictionary<Perk, int> GetPerkWeights(string action, BaseItem baseItem, List<Perk> selectedPerks) {
            var requiredKits = GetRequiredKitAmount(selectedPerks);
            var perkMultiplier = GetPerkMultiplier(selectedPerks.Count, action);
            var itemPerkKeys = baseItem.perks.Select(el => el.Perk);
            var perkWeights = GetAvailablePerkSettingsForItem(baseItem) .Where(el => action == "cmdaddperk" || itemPerkKeys.Contains(el.Key)) .ToDictionary(el => el.Key, el => el.Value.perkWeight);
            // modify perk weights with selected kits
            foreach (var kit in requiredKits) perkWeights[kit.Key] += (int)(perkWeights[kit.Key] * requiredKits[kit.Key] * perkMultiplier);
            return perkWeights;
        }
        public bool IsWeightedAction(BasePlayer player, string action) {
            if (permission.UserHasPermission(player.UserIDString, perm_perk_bypass_weighting)) return false;
            switch (action) {
                case "cmdaddperk" : return config.craft_settings.add_perk_settings.weight_system.enabled;
                case "cmdremoveperk" : return config.craft_settings.remove_perk_settings.weight_system.enabled;
                case "cmdrandomizeperkvalues" : return config.craft_settings.randomize_perk_settings.allow_lucky_rolls;
            }
            return false;
        }
        public bool RequiresKit(string action) {
            switch (action) {
                case "cmdaddperk" : return config.craft_settings.add_perk_settings.weight_system.requires_kit;
                case "cmdremoveperk" : return config.craft_settings.remove_perk_settings.weight_system.requires_kit;
                case "cmdrandomizeperkvalues" : return config.craft_settings.randomize_perk_settings.requires_kit;
            }
            return false;
        }
#endregion Actions: Perks
#region Actions:Payments
        CraftItem GetCraftItem(string action) {
            CraftItem item = null;
            switch (action) {
                case "cmdaddperk" : return config.craft_settings.add_perk_settings.craft_item;
                case "cmdremoveperk" : return config.craft_settings.remove_perk_settings.craft_item;
                case "cmdrandomizeperkvalues" : return config.craft_settings.randomize_perk_settings.randomize_perk_item;
                case "cmdunveilperk" : return config.craft_settings.unveil_perk_settings.craft_item;
                default : return null;
            }
        }
        int GetCraftItemAmountRequired(CraftItem item, List<Perk> selectedPerks = null) {
            if (item == null) return 0;
            int amountRequired = item.amount;
            if (selectedPerks == null) return amountRequired;
            foreach (Perk perk in selectedPerks) if (item.cost_per_kit.TryGetValue(perk, out var value)) amountRequired += value;
            return amountRequired;
        }
        int CraftItemAmountAvailable(BasePlayer player, CraftItem item) {
            if (item == null) return 0;
            return ItemAmountAvailable(player, item.shortname, item.skin, item.display_name);
        }
        int ItemAmountAvailable(BasePlayer player, string shortname, ulong skin, string name) {
     
// ... [Code preview truncated due to length. Full source in attached file] ...

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