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

FREE Loadouts : 0.1.20 0.1.20

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Game.Rust.Cui;
using Oxide.Core.Plugins;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("Loadouts", "k1lly0u", "0.1.20")]
    class Loadouts : RustPlugin {
#region Fields
        [PluginReference]
        Plugin Economics, ImageLibrary, ServerRewards, ZoneManager;
        private LoadoutData loadoutData;
        private CostData costData;
        private Hash<string, int> itemLimits;
        private DynamicConfigFile loadout;
        private DynamicConfigFile costs;
        private DynamicConfigFile supplysignals;
        private DynamicConfigFile limits;
        private int scrapItemID;
        private Hash<ulong, CreatorData> loadoutCreators = new Hash<ulong, CreatorData>();
        private Hash<uint, LoadoutData.InventoryData> activeSupplySignals = new Hash<uint, LoadoutData.InventoryData>();
        //For FancyDrop
        private HashSet<uint> activeSupplySignalEntIds = new HashSet<uint>();
        private Hash<ItemCategory, List<ItemDefinition>> itemsByCategory = new Hash<ItemCategory, List<ItemDefinition>>();
        public static Loadouts Instance {
            get;
            private set;
        }
        private static GiveType giveType;
        private GiveType giveTypeAutoKit;
        private static RaycastHit raycastHit;
        private const string PERM_ITEM_SELECTOR = "loadouts.itemselector";
        private const string PERM_NO_CREATION_COOLDOWN = "loadouts.nocreationcooldown";
        private const string UI_LOADOUT_MENU = "loadouts.menu";
        private const string SUPPLYDROP_PREFAB = "assets/prefabs/misc/supply drop/supply_drop.prefab";
        private const string SMOKE_PREFAB = "assets/bundled/prefabs/fx/smoke_signal_full.prefab";
        private const string PARACHUTE_PREFAB = "assets/prefabs/misc/parachute/parachute.prefab";
        private const string HELIEXPLOSION_EFFECT = "assets/prefabs/npc/patrol helicopter/effects/heli_explosion.prefab";
        private const string BRADLEY_CANNON_EFFECT = "assets/prefabs/npc/m2bradley/effects/maincannonattack.prefab";
        private const string SUPPLYSIGNAL_ITEM = "supply.signal";
        private const ulong SUPPLYSIGNAL_SKIN = 2216930422;
        private const int RAYCAST_LAYERS = 1 << 0 | 1 << 4 | 1 << 8 | 1 << 10 | 1 << 16 | 1 << 21 | 1 << 23 | 1 << 25 | 1 << 26;
        private enum GiveType {
            SupplyDrop, GiveItems
        }
#endregion
#region Oxide Hooks
        private void Loaded() {
            loadout = Interface.Oxide.DataFileSystem.GetFile("Loadouts/player_loadouts");
            costs = Interface.Oxide.DataFileSystem.GetFile("Loadouts/item_costs");
            supplysignals = Interface.Oxide.DataFileSystem.GetFile("Loadouts/supply_signals");
            limits = Interface.Oxide.DataFileSystem.GetFile("Loadouts/item_limits");
            Instance = this;
            lang.RegisterMessages(Messages, this);
            permission.RegisterPermission(PERM_ITEM_SELECTOR, this);
            permission.RegisterPermission(PERM_NO_CREATION_COOLDOWN, this);
            foreach (string perm in configData.Limits.Keys) permission.RegisterPermission(perm, this);
            foreach (string command in configData.Commands) cmd.AddChatCommand(command, this, cmdLoadout);
            ExitColor = configData.Colors.Exit.ToColor();
            ProfileColor = configData.Colors.Profile.ToColor();
            HeaderColor = configData.Colors.Header.ToColor();
            PanelColor = configData.Colors.Panel.ToColor();
            BackgroundColor = configData.Colors.Background.ToColor();
            giveType = configData.GiveType.Equals("SupplyDrop", StringComparison.InvariantCultureIgnoreCase) ? GiveType.SupplyDrop : GiveType.GiveItems;
            giveTypeAutoKit = configData.AutoKitGiveType.Equals("SupplyDrop", StringComparison.InvariantCultureIgnoreCase) ? GiveType.SupplyDrop : GiveType.GiveItems;
            if (!configData.AutoKits) {
                Unsubscribe(nameof(CanRedeemKit));
                Unsubscribe(nameof(OnPlayerRespawned));
            }
            if (giveType != GiveType.SupplyDrop) {
                Unsubscribe(nameof(OnExplosiveThrown));
                Unsubscribe(nameof(OnExplosiveDropped));
                Unsubscribe(nameof(OnSupplyDropLanded));
            }
        }
        private void OnServerInitialized() {
            LoadData();
            SortItemsByCategory();
        }
        private void OnExplosiveThrown(BasePlayer player, SupplySignal supplySignal, ThrownWeapon thrownWeapon) => OnExplosiveDropped(player, supplySignal, thrownWeapon);
        private void OnExplosiveDropped(BasePlayer player, SupplySignal supplySignal, ThrownWeapon thrownWeapon) {
            LoadoutData.InventoryData inventoryData;
            if (!activeSupplySignals.TryGetValue(thrownWeapon?.GetItem()?.uid ?? 0, out inventoryData)) return;
            activeSupplySignals.Remove(thrownWeapon.GetItem().uid);
            if (supplySignal.IsValid()) {
                activeSupplySignalEntIds.Add(supplySignal.net.ID);
                timer.In(1f, () => activeSupplySignalEntIds.Remove(supplySignal.net.ID));
            }
            supplySignal.CancelInvoke(supplySignal.Explode);
            ChatMessage(player, string.Format(msg("Notification.LoadoutInbound", player.UserIDString), configData.Drop.Time));
            Effect.server.Run(SMOKE_PREFAB, supplySignal, 0, Vector3.zero, Vector3.zero, null, false);
            supplySignal.SetFlag(BaseEntity.Flags.On, true, false, true);
            supplySignal.SendNetworkUpdateImmediate(false);
            supplySignal.Invoke(() => SendDrop(supplySignal, inventoryData), configData.Drop.Time);
        }
        private void OnSupplyDropLanded(SupplyDrop supplyDrop) => supplyDrop.GetComponent<DropBehaviour>()?.OnGroundCollision();
        private object CanStackItem(Item item1, Item item2) {
            if (item1 == null || item2 == null) return null;
            if (!item1.info.shortname.Equals(SUPPLYSIGNAL_ITEM)) return null;
            if (item1.skin.Equals(SUPPLYSIGNAL_SKIN) || item2.skin.Equals(SUPPLYSIGNAL_SKIN)) return false;
            return null;
        }
        private object CanRedeemKit(BasePlayer player) {
            if (!HasAnyPermission(player)) return null;
            string loadout = loadoutData.GetRespawnLoadout(player);
            if ((string.IsNullOrEmpty(loadout) || loadoutData.GetLoadouts(player)?.Count == 0) && loadoutData.defaultLoadout == null) return null;
            if ((uint)Facepunch.Math.Epoch.Current - player.lifeStory.timeBorn > 5) return null;
            return false;
        }
        private void OnPlayerRespawned(BasePlayer player) {
            if (player == null) return;
            if (!HasAnyPermission(player)) return;
            LoadoutData.InventoryData inventoryData = null;
            bool isDefaultLoadout = false;
            string loadout = loadoutData.GetRespawnLoadout(player);
            if (!string.IsNullOrEmpty(loadout)) {
                loadoutData.GetLoadouts(player)?.TryGetValue(loadout, out inventoryData);
            }
            if (loadoutData.defaultLoadout != null && inventoryData == null) {
                inventoryData = loadoutData.defaultLoadout;
                isDefaultLoadout = true;
            }
            if (inventoryData != null) {
                player.inventory.Strip();
                if (giveTypeAutoKit == GiveType.SupplyDrop) {
                    Item item = ItemManager.CreateByName(SUPPLYSIGNAL_ITEM, 1, SUPPLYSIGNAL_SKIN);
                    player.GiveItem(item, BaseEntity.GiveItemReason.PickedUp);
                    activeSupplySignals.Add(item.uid, inventoryData);
                    ChatMessage(player, msg("Notification.SignalGiven", player.UserIDString));
                }
                else {
                    inventoryData.Give(player);
                    ChatMessage(player, isDefaultLoadout ? msg("Notification.ClaimedDefaultLoadout", player.UserIDString) : string.Format(msg("Notification.ClaimedLoadout", player.UserIDString), loadout));
                }
            }
        }
        private void OnServerSave() => SaveData();
        private void Unload() {
            foreach(BasePlayer player in BasePlayer.activePlayerList) CuiHelper.DestroyUi(player, UI_LOADOUT_MENU);
            DropBehaviour[] activeDrops = UnityEngine.Object.FindObjectsOfType<DropBehaviour>();
            for (int i = 0; i < activeDrops.Length; i++) UnityEngine.Object.Destroy(activeDrops[i]);
            SaveSupplySignals();
            configData = null;
            Instance = null;
        }
#endregion
#region Functions
        private void SortItemsByCategory() {
            scrapItemID = ItemManager.FindItemDefinition("scrap").itemid;
            foreach(ItemDefinition itemDefinition in ItemManager.itemList) {
                if (itemDefinition.shortname.Contains("vehicle.chassis") || itemDefinition.shortname.Contains("vehicle.module")) continue;
                if (configData.BlockedItems.Contains(itemDefinition.shortname)) continue;
                if (!configData.AllowedCategories.Contains(itemDefinition.category.ToString()) && !configData.AllowedItems.Contains(itemDefinition.shortname)) continue;
                if (!itemsByCategory.ContainsKey(itemDefinition.category)) itemsByCategory[itemDefinition.category] = new List<ItemDefinition>();
                itemsByCategory[itemDefinition.category].Add(itemDefinition);
                loadImageBuffer.Add(new KeyValuePair<string, ulong>(itemDefinition.shortname, 0UL));
            }
            foreach (KeyValuePair<ItemCategory, List<ItemDefinition>> kvp in itemsByCategory) {
                kvp.Value.Sort(delegate (ItemDefinition a, ItemDefinition b) {
                    return a.shortname.CompareTo(b.shortname);
                }
                );
            }
            ImageLibrary.Call("LoadImageList", "Loadout item icon pre-load", loadImageBuffer, null);
            ImageLibrary.Call("AddImage", configData.DefaultIcon, DEFAULT_LOADOUT, 0UL);
        }
        private bool IsAllowedItem(ItemDefinition itemDefinition) {
            List<ItemDefinition> list;
            if (!itemsByCategory.TryGetValue(itemDefinition.category, out list)) return false;
            if (!list.Contains(itemDefinition)) return false;
            return true;
        }
        private void SendDrop(SupplySignal supplySignal, LoadoutData.InventoryData inventoryData) {
            Vector3 position = supplySignal.transform.position;
            position.y = 450f;
            SupplyDrop supplyDrop = GameManager.server.CreateEntity(SUPPLYDROP_PREFAB, position, Quaternion.identity) as SupplyDrop;
            supplyDrop.initialLootSpawn = false;
            supplyDrop.Spawn();
            supplyDrop.gameObject.AddComponent<DropBehaviour>().Setup(supplySignal, inventoryData);
            Effect.server.Run(BRADLEY_CANNON_EFFECT, supplyDrop.transform.position, Vector3.zero, null, true);
            supplyDrop.Invoke(() => Effect.server.Run(HELIEXPLOSION_EFFECT, supplyDrop.transform.position, Vector3.zero, null, true), 0.5f);
        }
        private static void ClearContainer(ItemContainer itemContainer) {
            if (itemContainer == null || itemContainer.itemList == null) return;
            while (itemContainer.itemList.Count > 0) {
                Item item = itemContainer.itemList[0];
                item.RemoveFromContainer();
                item.Remove(0f);
            }
        }
        private bool ChargeForLoadout(BasePlayer player, int cost) {
            if (configData.Cost.Enabled) {
                int playerCurrency = 0;
                switch (configData.Cost.Currency) {
                    case "ServerRewards" : playerCurrency = (int)ServerRewards?.Call("CheckPoints", player.userID);
                    break;
                    case "Economics" : playerCurrency = Convert.ToInt32((double)Economics?.Call("Balance", player.UserIDString));
                    break;
                    case "Scrap" : playerCurrency = player.inventory.GetAmount(scrapItemID);
                    break;
                    default : PrintError($"Invalid currency type set in config.Unable to issue loadouts!");
                    return false;
                }
                if (playerCurrency < cost) return false;
                switch (configData.Cost.Currency) {
                    case "ServerRewards" : ServerRewards?.Call("TakePoints", player.userID, cost);
                    break;
                    case "Economics" : Economics?.Call("Withdraw", player.UserIDString, cost);
                    break;
                    case "Scrap" : player.inventory.Take(null, scrapItemID, cost);
                    break;
                }
            }
            return true;
        }
        private bool InClaimZone(BasePlayer player) {
            if (configData.Zones.Length > 0 && ZoneManager) {
                bool isInZone = false;
                for (int i = 0; i < configData.Zones.Length; i++) {
                    if ((bool)ZoneManager.Call("IsPlayerInZone", configData.Zones[i], player)) {
                        isInZone = true;
                        break;
                    }
                }
                if (!isInZone) return false;
            }
            return true;
        }
        private bool HasLoadoutSignal(BasePlayer player) {
            List<Item> list = Facepunch.Pool.GetList<Item>();
            player.inventory.AllItemsNoAlloc(ref list);
            bool hasItem = false;
            foreach (Item item in list) {
                if (item.info.shortname.Equals(SUPPLYSIGNAL_ITEM) && item.skin.Equals(SUPPLYSIGNAL_SKIN)) {
                    hasItem = true;
                    break;
                }
            }
            return hasItem;
        }
        private object ShouldFancyDrop(uint netId) => activeSupplySignalEntIds.Contains(netId) ? (object)true : null;
        private int GetItemLimit(string shortname) {
            int limit;
            if (itemLimits.TryGetValue(shortname, out limit)) return limit;
            return 1;
        }
#endregion
#region ImageLibrary
        private List<KeyValuePair<string, ulong>> loadImageBuffer = new List<KeyValuePair<string, ulong>>();
        private string GetImage(string shortname, ulong skinID = 0UL) {
            if (skinID != 0UL) {
                if (!(bool)ImageLibrary?.Call("HasImage", shortname, skinID)) {
                    loadImageBuffer.Clear();
                    loadImageBuffer.Add(new KeyValuePair<string, ulong>(shortname, skinID));
                    ImageLibrary?.Call("LoadImageList", Title, loadImageBuffer, null);
                }
            }
            return (string)ImageLibrary?.Call("GetImage", shortname, skinID) ?? string.Empty;
        }
#endregion
#region Helpers
        private static void ChatMessage(BasePlayer player, string text) => player.ChatMessage(msg("Message.Prefix", player.UserIDString) + text);
        private bool HasAnyPermission(BasePlayer player) => configData.Limits.Keys.Any(x => permission.UserHasPermission(player.UserIDString, x));
        private int CurrentProfileCount(BasePlayer player) => loadoutData.GetLoadouts(player)?.Count ?? 0;
        private int MaxAllowedProfiles(BasePlayer player) {
            int max = 0;
            foreach(KeyValuePair<string, ConfigData.Limitations> kvp in configData.Limits) {
                if (permission.UserHasPermission(player.UserIDString, kvp.Key) && kvp.Value.MaxProfiles > max) max = kvp.Value.MaxProfiles;
            }
            return max;
        }
        private static int GetCooldownTime(BasePlayer player) {
            int time = int.MaxValue;
            foreach (KeyValuePair<string, ConfigData.Limitations> kvp in configData.Limits) {
                if (Instance.permission.UserHasPermission(player.UserIDString, kvp.Key) && kvp.Value.Cooldown < time) time = kvp.Value.Cooldown;
            }
            return time;
        }
        private static int GetCreationCooldownTime(BasePlayer player) {
            int time = int.MaxValue;
            foreach (KeyValuePair<string, ConfigData.Limitations> kvp in configData.Limits) {
                if (Instance.permission.UserHasPermission(player.UserIDString, kvp.Key) && kvp.Value.CreateCooldown < time) time = kvp.Value.CreateCooldown;
            }
            return time;
        }
        private static ConfigData.Limitations GetLimitations(BasePlayer player) {
            ConfigData.Limitations limits = null;
            foreach (KeyValuePair<string, ConfigData.Limitations> kvp in configData.Limits) {
                if (Instance.permission.UserHasPermission(player.UserIDString, kvp.Key)) limits = kvp.Value;
            }
            return limits;
        }
        private bool HasSpace(ItemContainer itemContainer, int count) => itemContainer.capacity - itemContainer.itemList.Count >= count;
        private static double CurrentTime() => DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds;
        private string FormatTime(double time) {
            TimeSpan dateDifference = TimeSpan.FromSeconds((float)time);
            int days = dateDifference.Days;
            int hours = dateDifference.Hours;
            int mins = dateDifference.Minutes;
            int secs = dateDifference.Seconds;
            if (days > 0) return string.Format("{0:00}d:{1:00}h:{2:00}m:{3:00}s", days, hours, mins, secs);
            else if (hours > 0) return string.Format("{0:00}h:{1:00}m:{2:00}s", hours, mins, secs);
            else if (mins > 0) return string.Format("{0:00}m:{1:00}s", mins, secs);
            else return string.Format("{0}s", secs);
        }
#endregion
#region Drop Component
        private class DropBehaviour : MonoBehaviour {
            private SupplyDrop entity;
            private Rigidbody rb;
            private Transform tr;
            private float heightAtPosition;
            private float distToTarget;
            private bool hasDeployedChute = false;
            private SupplySignal supplySignal;
            private BaseEntity parachute;
            private Vector3 velocityEnter;
            private void Awake() {
                entity = GetComponent<SupplyDrop>();
                rb = GetComponent<Rigidbody>();
                tr = entity.transform;
            }
            private void Start() {
                entity.RemoveParachute();
                rb.isKinematic = false;
                rb.useGravity = true;
                rb.mass = 1.25f;
                rb.interpolation = RigidbodyInterpolation.Interpolate;
                rb.drag = 0.1f;
                rb.angularDrag = 0.1f;
                rb.AddForce(Vector3.down * configData.Drop.Velocity, ForceMode.Impulse);
                if (Physics.Raycast(tr.position + Vector3.down, Vector3.down, out raycastHit, 500f, RAYCAST_LAYERS, QueryTriggerInteraction.Collide)) heightAtPosition = raycastHit.point.y;
                else heightAtPosition = TerrainMeta.HeightMap.GetHeight(tr.position);
            }
            internal void Setup(SupplySignal supplySignal, LoadoutData.InventoryData inventoryData) {
                this.supplySignal = supplySignal;
                entity.Invoke(()=> inventoryData.Give(entity), 2f);
            }
            private void Update() {
                distToTarget = tr.position.y - heightAtPosition;
                if (distToTarget < configData.Drop.DeployDistance) {
                    if (!hasDeployedChute) {
                        parachute = GameManager.server.CreateEntity(PARACHUTE_PREFAB, tr.position, Quaternion.identity);
                        parachute.SetParent(entity, "parachute_attach", false, false);
                        parachute.transform.localPosition = Vector3.zero;
                        parachute.transform.localRotation = Quaternion.identity;
                        parachute.enableSaving = false;
                        parachute.Spawn();
                        velocityEnter = rb.velocity;
                        hasDeployedChute = true;
                    }
                    rb.velocity = Vector3.Lerp(velocityEnter, Vector3.zero, 1f - Mathf.InverseLerp(0f, configData.Drop.DeployDistance, distToTarget));
                }
            }
            internal void OnGroundCollision() {
                supplySignal?.Kill(BaseNetworkable.DestroyMode.None);
                parachute?.Kill(BaseNetworkable.DestroyMode.None);
                Destroy(this);
            }
        }
#endregion
#region UI
        public static class UI {
            public static CuiElementContainer Container(string panelName, string color, UI4 dimensions, bool useCursor = false, string parent = "Overlay") {
                CuiElementContainer container = new CuiElementContainer() {
                    {
                        new CuiPanel {
                            Image = {
                                Color = color
                            }
                            , RectTransform = {
                                AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax()
                            }
                            , CursorEnabled = useCursor
                        }
                        , new CuiElement().Parent = parent, panelName.ToString()
                    }
                }
                ;
                return container;
            }
            public static CuiElementContainer BlurContainer(string panelName, UI4 dimensions, string color = "0 0 0 0.55") {
                CuiElementContainer container = new CuiElementContainer() {
                    {
                        new CuiPanel {
                            Image = {
                                Color = color, Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat"
                            }
                            , RectTransform = {
                                AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax()
                            }
                            , CursorEnabled = true
                        }
                        , new CuiElement().Parent = "Hud", panelName.ToString()
                    }
                }
                ;
                return container;
            }
            public static void Panel(ref CuiElementContainer container, string panel, string color, UI4 dimensions, bool cursor = false) {
                container.Add(new CuiPanel {
                    Image = {
                        Color = color
                    }
                    , RectTransform = {
                        AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax()
                    }
                    , CursorEnabled = cursor
                }
                , panel.ToString());
            }
            public static void BlurPanel(ref CuiElementContainer container, string panel, UI4 dimensions, string color = "0 0 0 0.5") {
                container.Add(new CuiPanel {
                    Image = {
                        Color = color, Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat"
                    }
                    , RectTransform = {
                        AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax()
                    }
                    , CursorEnabled = false
                }
                , panel, CuiHelper.GetGuid());
            }
            public static void Label(ref CuiElementContainer container, string panel, string text, int size, UI4 dimensions, TextAnchor align = TextAnchor.MiddleCenter, FontStyle fontStyle = FontStyle.RobotoCondensed) {
                container.Add(new CuiLabel {
                    Text = {
                        FontSize = size, Align = align, Text = text, Font = ToFontString(fontStyle)
                    }
                    , RectTransform = {
                        AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax()
                    }
                }
                , panel.ToString());
            }
            public static void Button(ref CuiElementContainer container, string panel, string color, string text, int size, UI4 dimensions, string command, TextAnchor align = TextAnchor.MiddleCenter, FontStyle fontStyle = FontStyle.RobotoCondensed) {
                container.Add(new CuiButton {
                    Button = {
                        Color = color, Command = command, FadeIn = 0f
                    }
                    , RectTransform = {
                        AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax()
                    }
                    , Text = {
                        Text = text, FontSize = size, Align = align, Font = ToFontString(fontStyle)
                    }
                }
                , panel.ToString());
            }
            public static void Image(ref CuiElementContainer container, string panel, string png, UI4 dimensions) {
                container.Add(new CuiElement {
                    Name = CuiHelper.GetGuid(), Parent = panel, Components = {
                        new CuiRawImageComponent {
                            Png = png
                        }
                        , new CuiRectTransformComponent {
                            AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax()
                        }
                    }
                }
                );
            }
            public static void Input(ref CuiElementContainer container, string panel, string text, int size, string command, UI4 dimensions) {
                container.Add(new CuiElement {
                    Name = CuiHelper.GetGuid(), Parent = panel, Components = {
                        new CuiInputFieldComponent {
                            Align = TextAnchor.MiddleLeft, CharsLimit = 300, Command = command, FontSize = size, IsPassword = false, Text = text
                        }
                        , new CuiRectTransformComponent {
                            AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax()
                        }
                    }
                }
                );
            }
            public static string Color(string hexColor, float alpha) {
                if (hexColor.StartsWith("#")) hexColor = hexColor.Substring(1);
                int red = int.Parse(hexColor.Substring(0, 2), NumberStyles.AllowHexSpecifier);
                int green = int.Parse(hexColor.Substring(2, 2), NumberStyles.AllowHexSpecifier);
                int blue = int.Parse(hexColor.Substring(4, 2), NumberStyles.AllowHexSpecifier);
                return $"{(double)red / 255} {(double)green / 255} {(double)blue / 255} {alpha}";
            }
            public enum FontStyle {
                DroidSansMono, RobotoCondensed, RobotoCondensedBold, PermanantMarker
            }
            private static string ToFontString(FontStyle fontStyle) {
                switch (fontStyle) {
                    case FontStyle.DroidSansMono : return "droidsansmono.ttf";
                    case FontStyle.PermanantMarker : return "permanentmarker.ttf";
                    case FontStyle.RobotoCondensed : return "robotocondensed-regular.ttf";
                    case FontStyle.RobotoCondensedBold : default : return "robotocondensed-bold.ttf";
                }
            }
        }
        public class UI4 {
            [JsonProperty(PropertyName = "Left (0.0 - 1.0)")]
            public float xMin;
            [JsonProperty(PropertyName = "Bottom (0.0 - 1.0)")]
            public float yMin;
            [JsonProperty(PropertyName = "Right (0.0 - 1.0)")]
            public float xMax;
            [JsonProperty(PropertyName = "Top (0.0 - 1.0)")]
            public float yMax;
            public UI4(float xMin, float yMin, float xMax, float yMax) {
                this.xMin = xMin;
                this.yMin = yMin;
                this.xMax = xMax;
                this.yMax = yMax;
            }
            public string GetMin() => $"{xMin} {yMin}";
            public string GetMax() => $"{xMax} {yMax}";
        }
#endregion
#region UI Methods
        public string ExitColor {
            get;
            private set;
        }
        public string ProfileColor {
            get;
            private set;
        }
        public string HeaderColor {
            get;
            private set;
        }
        public string PanelColor {
            get;
            private set;
        }
        public string BackgroundColor {
            get;
            private set;
        }
        public const string COLOR_INVISIBLE = "0 0 0 0";
        public const string DEFAULT_LOADOUT = "loadouts-default";
        private string _defaultLoadoutIcon;
        private string DefaultLoadoutIcon {
            get {
                if (string.IsNullOrEmpty(_defaultLoadoutIcon)) _defaultLoadoutIcon = GetImage(DEFAULT_LOADOUT, 0UL);
                return _defaultLoadoutIcon;
            }
        }
#region Loadout Menu
        private void OpenLoadoutMenu(BasePlayer player, string loadout, int page = 0) {
            CuiElementContainer container = UI.BlurContainer(UI_LOADOUT_MENU, new UI4(0.3f, 0.275f, 0.7185f, 0.725f), BackgroundColor);
            Hash<string, LoadoutData.InventoryData> loadouts = loadoutData.GetLoadouts(player);
            // Header
            UI.Panel(ref container, UI_LOADOUT_MENU, PanelColor, new UI4(0.005f, 0.9f, 0.995f, 0.99f));
            UI.Label(ref container, UI_LOADOUT_MENU, string.IsNullOrEmpty(loadout) ? msg("UI.Title", player.UserIDString) : string.Format(msg("UI.Title.Name", player.UserIDString), loadout), 18, new UI4(0.01f, 0.9f, 0.995f, 0.99f), TextAnchor.MiddleLeft, UI.FontStyle.RobotoCondensedBold);
            UI.Button(ref container, UI_LOADOUT_MENU, ExitColor, "✘", 12, new UI4(0.95f, 0.91f, 0.99f, 0.98f), "loadoutui.close");
            // Loadout Selection
            UI.Panel(ref container, UI_LOADOUT_MENU, PanelColor, new UI4(0.005f, 0.01f, 0.3f, 0.89f));
            UI.Panel(ref container, UI_LOADOUT_MENU, HeaderColor, new UI4(0.005f, 0.83f, 0.3f, 0.89f));
            UI.Label(ref container, UI_LOADOUT_MENU, msg("UI.Profiles", player.UserIDString), 12, new UI4(0.01f, 0.83f, 0.3f, 0.89f), TextAnchor.MiddleLeft, UI.FontStyle.RobotoCondensed);
            UI.Button(ref container, UI_LOADOUT_MENU, ExitColor, msg("UI.CreateLoadout", player.UserIDString), 12, new UI4(0.01f, 0.76f, 0.295f, 0.82f), "loadoutui.create", TextAnchor.MiddleCenter);
            if (loadouts != null) {
                const float loadoutMin = 0.69f;
                const float loadoutHeight = 0.06f;
                const float loadoutSpacing = 0.01f;
                int index = page * 10;
                int limit = Mathf.Min((page + 1) * 10, loadouts.Count);
                string lastClaimedLoadout = loadoutData.GetRespawnLoadout(player);
                for (int i = index; i < limit; i++) {
                    float yMin = loadoutMin - ((loadoutHeight + loadoutSpacing) * (i - index));
                    string loadoutName = loadouts.ElementAt(i).Key;
                    UI.Button(ref container, UI_LOADOUT_MENU, ProfileColor, loadoutName, 12, new UI4(0.01f, yMin, 0.295f, yMin + loadoutHeight), $"loadoutui.open {loadouts.ElementAt(i).Key} {page}", TextAnchor.MiddleCenter);
                    if (!string.IsNullOrEmpty(lastClaimedLoadout) && loadoutName.Equals(lastClaimedLoadout)) UI.Image(ref container, UI_LOADOUT_MENU, DefaultLoadoutIcon, new UI4(0.26f, yMin, 0.295f, yMin + loadoutHeight));
                }
                if (page > 0) UI.Button(ref container, UI_LOADOUT_MENU, ExitColor, "< < <", 12, new UI4(0.01f, 0.01f, 0.145f, 0.05f), $"loadoutui.open {loadout} {page -1}");
                if (limit < loadouts.Count) UI.Button(ref container, UI_LOADOUT_MENU, ExitColor, "> > >", 12, new UI4(0.15f, 0.01f, 0.295f, 0.05f), $"loadoutui.open {loadout} {page + 1}");
                // Loadout Viewer
                if (!string.IsNullOrEmpty(loadout)) {
                    LoadoutData.InventoryData inventoryData = loadouts[loadout];
                    UI.Panel(ref container, UI_LOADOUT_MENU, PanelColor, new UI4(0.31f, 0.01f, 0.995f, 0.89f));
                    //Belt
                    UI.Panel(ref container, UI_LOADOUT_MENU, HeaderColor, new UI4(0.31f, 0.83f, 0.995f, 0.89f));
                    UI.Label(ref container, UI_LOADOUT_MENU, msg("Container.Belt", player.UserIDString), 12, new UI4(0.315f, 0.83f, 0.995f, 0.89f), TextAnchor.MiddleLeft);
                    LayoutProfileItems(ref container, UI_LOADOUT_MENU, inventoryData.containerBelt, 0.695f);
                    //Wear
                    UI.Panel(ref container, UI_LOADOUT_MENU, HeaderColor, new UI4(0.31f, 0.625f, 0.995f, 0.685f));
                    UI.Label(ref container, UI_LOADOUT_MENU, msg("Container.Wear", player.UserIDString), 12, new UI4(0.315f, 0.625f, 0.995f, 0.685f), TextAnchor.MiddleLeft);
                    LayoutProfileItems(ref container, UI_LOADOUT_MENU, inventoryData.containerWear, 0.49f);
                    //Main
                    UI.Panel(ref container, UI_LOADOUT_MENU, HeaderColor, new UI4(0.31f, 0.42f, 0.995f, 0.48f));
                    UI.Label(ref container, UI_LOADOUT_MENU, msg("Container.Main", player.UserIDString), 12, new UI4(0.315f, 0.42f, 0.995f, 0.48f), TextAnchor.MiddleLeft);
                    LayoutProfileItems(ref container, UI_LOADOUT_MENU, inventoryData.containerMain, 0.285f);
                    //Spawn Helper
                    UI.BlurPanel(ref container, UI_LOADOUT_MENU, new UI4(0f, -0.07f, 1f, 0f), BackgroundColor);
                    if (inventoryData.IsOnCooldown()) UI.Button(ref container, UI_LOADOUT_MENU, HeaderColor, string.Format(msg("UI.Cooldown", player.UserIDString), FormatTime(inventoryData.CooldownRemaining)), 12, new UI4(0.71f, -0.06f, 0.995f, 0f), "");
                    else {
                        if (configData.Cost.Enabled) UI.Button(ref container, UI_LOADOUT_MENU, HeaderColor, string.Format(msg("UI.Claim.Cost", player.UserIDString), inventoryData.GetCost(player), msg("Currency."+configData.Cost.Currency, player.UserIDString)), 12, new UI4(0.71f, -0.06f, 0.995f, 0f), $"loadoutui.claim {loadout}");
                        else UI.Button(ref container, UI_LOADOUT_MENU, HeaderColor, msg("UI.Claim", player.UserIDString), 12, new UI4(0.71f, -0.06f, 0.995f, 0f), $"loadoutui.claim {loadout}");
                    }
                    UI.Button(ref container, UI_LOADOUT_MENU, ExitColor, msg("UI.Delete", player.UserIDString), 12, new UI4(0.415f, -0.06f, 0.7f, 0f), $"loadoutui.delete {loadout}");
                    if (configData.AutoKits) UI.Button(ref container, UI_LOADOUT_MENU, HeaderColor, !string.IsNullOrEmpty(lastClaimedLoadout) && lastClaimedLoadout.Equals(loadout) ? msg("UI.RemoveDefault", player.UserIDString) : msg("UI.SetDefault", player.UserIDString), 12, new UI4(0.005f, -0.06f, 0.295f, 0f), $"loadoutui.setdefault {loadout}");
                }
            }
            // Send to client
            CuiHelper.DestroyUi(player, UI_LOADOUT_MENU);
            CuiHelper.AddUi(player, container);
        }
        private void LayoutProfileItems(ref CuiElementContainer container, string panel, LoadoutData.InventoryData.ItemData[] items, float yMin, float xMin = 0.315f, float width = 0.08f, float height = 0.125f) {
            for (int i = 0; i < items.Length; i++) {
                float x = xMin + ((width + 0.005f) * (i >= 16 ? i - 16 : i >= 8 ? i - 8 : i));
                float y = i >= 16 ? yMin - 0.26f : i >= 8 ? yMin - 0.13f : yMin;
                UI4 pos = new UI4(x, y, x + width, y + height);
                UI.BlurPanel(ref container, panel, pos);
                LoadoutData.InventoryData.ItemData item = items[i];
                if (item != null) {
                    UI.Image(ref container, panel, GetImage(item.shortname, item.skin), pos);
                    if (item.amount > 1) UI.Label(ref container, panel, $"x{item.amount}", 8, pos, TextAnchor.LowerRight);
                }
            }
        }
#endregion
#region Creator Menu
        private void OpenCreationMenu(BasePlayer player, string loadout) {
            CuiElementContainer container = UI.BlurContainer(UI_LOADOUT_MENU, new UI4(0.355f, 0.275f, 0.645f, 0.725f), BackgroundColor);
            CreatorData creatorData;
            if (!loadoutCreators.TryGetValue(player.userID, out creatorData)) {
                creatorData = loadoutCreators[player.userID] = new CreatorData(player);
                if (!creatorData.CanItemSelect) creatorData.Inventory.CopyItemsFrom(player);
            }
            // Header
            UI.Panel(ref container, UI_LOADOUT_MENU, PanelColor, new UI4(0.005f, 0.9f, 0.99f, 0.99f));
            UI.Label(ref container, UI_LOADOUT_MENU, creatorData.IsDefaultLoadout ? msg("Creator.Title.DefaultLoadout", player.UserIDString) : msg("Creator.Title", player.UserIDString), 18, new UI4(0.02f, 0.9f, 0.99f, 0.99f), TextAnchor.MiddleLeft, UI.FontStyle.RobotoCondensedBold);
            UI.Button(ref container, UI_LOADOUT_MENU, ExitColor, "✘", 12, new UI4(0.92f, 0.91f, 0.985f, 0.98f), "loadoutui.open 0");
            UI.Panel(ref container, UI_LOADOUT_MENU, PanelColor, new UI4(0.01f, 0.01f, 0.99f, 0.89f));
            //Belt
            UI.Panel(ref container, UI_LOADOUT_MENU, HeaderColor, new UI4(0.01f, 0.83f, 0.99f, 0.89f));
            UI.Label(ref container, UI_LOADOUT_MENU, msg("Container.Belt", player.UserIDString), 12, new UI4(0.02f, 0.83f, 0.99f, 0.89f), TextAnchor.MiddleLeft);
            LayoutCreatorProfileButtons(ref container, UI_LOADOUT_MENU, creatorData.Inventory.containerBelt, ContainerType.Belt, creatorData.CanItemSelect, 0.695f);
            //Wear
            UI.Panel(ref container, UI_LOADOUT_MENU, HeaderColor, new UI4(0.01f, 0.625f, 0.99f, 0.685f));
            UI.Label(ref container, UI_LOADOUT_MENU, msg("Container.Wear", player.UserIDString), 12, new UI4(0.02f, 0.625f, 0.99f, 0.685f), TextAnchor.MiddleLeft);
            LayoutCreatorProfileButtons(ref container, UI_LOADOUT_MENU, creatorData.Inventory.containerWear, ContainerType.Wear, creatorData.CanItemSelect, 0.49f);
            //Main
            UI.Panel(ref container, UI_LOADOUT_MENU, HeaderColor, new UI4(0.01f, 0.42f, 0.99f, 0.48f));
            UI.Label(ref container, UI_LOADOUT_MENU, msg("Container.Main", player.UserIDString), 12, new UI4(0.02f, 0.42f, 0.99f, 0.48f), TextAnchor.MiddleLeft);
            LayoutCreatorProfileButtons(ref container, UI_LOADOUT_MENU, creatorData.Inventory.containerMain, ContainerType.Main, creatorData.CanItemSelect, 0.285f);
            //Save Helper
            UI.BlurPanel(ref container, UI_LOADOUT_MENU, new UI4(0f, -0.14f, 1f, 0f), BackgroundColor);
            if (configData.Cost.Enabled) UI.Label(ref container, UI_LOADOUT_MENU, string.Format(msg("Creator.Costs", player.UserIDString), creatorData.Inventory.CalculateCosts(creatorData.Limits.CostMultiplier), msg("Currency." + configData.Cost.Currency, player.UserIDString)), 12, new UI4(0.02f, -0.13f, 0.99f, -0.07f), TextAnchor.MiddleLeft);
            UI.Button(ref container, UI_LOADOUT_MENU, HeaderColor, msg("Creator.Save", player.UserIDString), 12, new UI4(0.7f, -0.13f, 0.99f, -0.07f), $"loadoutcreator.save {loadout}");
            UI.Button(ref container, UI_LOADOUT_MENU, ExitColor, msg("Creator.CopyInv", player.UserIDString), 12, new UI4(0.396f, -0.13f, 0.686f, -0.07f), "loadoutcreator.copyinv");
            //Input Field Fuckery
            if (!creatorData.IsDefaultLoadout) {
                UI.Panel(ref container, UI_LOADOUT_MENU, "0 0 0 0.7", new UI4(0.235f, -0.06f, 0.99f, 0f));
                UI.Label(ref container, UI_LOADOUT_MENU, msg("Creator.Profile", player.UserIDString), 12, new UI4(0.02f, -0.06f, 0.25f, 0f), TextAnchor.MiddleLeft);
                if (string.IsNullOrEmpty(creatorData.Name)) UI.Input(ref container, UI_LOADOUT_MENU, string.Empty, 12, "loadoutcreator.setname", new UI4(0.25f, -0.06f, 0.99f, 0f));
                else {
                    UI.Label(ref container, UI_LOADOUT_MENU, creatorData.Name, 12, new UI4(0.25f, -0.06f, 0.99f, 0f), TextAnchor.MiddleLeft);
                    UI.Button(ref container, UI_LOADOUT_MENU, ExitColor, "X", 12, new UI4(0.925f, -0.06f, 0.99f, 0f), "loadoutcreator.clearname");
                }
            }
            CuiHelper.DestroyUi(player, UI_LOADOUT_MENU);
            CuiHelper.AddUi(player, container);
        }
        private void LayoutCreatorProfileButtons(ref CuiElementContainer container, string panel, LoadoutData.InventoryData.ItemData[] items, ContainerType containerType, bool canSelectItems, float yMin, float xMin = 0.02f, float width = 0.1125f, float height = 0.125f) {
            for (int i = 0; i < items.Length; i++) {
                float x = xMin + ((width + 0.007f) * (i >= 16 ? i - 16 : i >= 8 ? i - 8 : i));
                float y = i >= 16 ? yMin - 0.26f : i >= 8 ? yMin - 0.13f : yMin;
                UI4 pos = new UI4(x, y, x + width, y + height);
                UI.BlurPanel(ref container, panel, pos);
                LoadoutData.InventoryData.ItemData item = items[i];
                if (item != null) {
                    UI.Image(ref container, panel, GetImage(item.shortname, item.skin), pos);
                    if (item.amount > 1) UI.Label(ref container, panel, $"x{item.amount}", 8, pos, TextAnchor.LowerRight);
                }
                if (canSelectItems) {
                    UI.Button(ref container, panel, COLOR_INVISIBLE, string.Empty, 0, pos, $"loadoutcreator.chooseitem {(int)containerType} {i}");
                    if (item != null) {
                        ItemDefinition itemDefinition = ItemManager.itemDictionaryByName[item.shortname];
                        int maxStackable = itemDefinition.category == ItemCategory.Weapon || itemDefinition.category == ItemCategory.Attire ? 1 : itemDefinition.stackable;
                        if (maxStackable > 1) UI.Button(ref container, panel, ProfileColor, "+", 10, new UI4(pos.xMax - (width * 0.25f), pos.yMax - (height * 0.25f), pos.xMax, pos.yMax), $"loadoutcreator.changeamount {(int)containerType} {i} {maxStackable} {item.shortname} {item.amount}");
                    }
                }
            }
        }
        private void OpenItemAmountMenu(BasePlayer player, string loadout, string shortname, int current, int max) {
            CuiElementContainer container = UI.BlurContainer(UI_LOADOUT_MENU, new UI4(0.355f, 0.4f, 0.645f, 0.6f), BackgroundColor);
            CreatorData creatorData;
            if (!loadoutCreators.TryGetValue(player.userID, out creatorData)) {
                creatorData = loadoutCreators[player.userID] = new CreatorData(player);
                if (!creatorData.CanItemSelect) creatorData.Inventory.CopyItemsFrom(player);
            }
            // Header
            UI.Panel(ref container, UI_LOADOUT_MENU, PanelColor, new UI4(0.005f, 0.775f, 0.99f, 0.975f));
            UI.Label(ref container, UI_LOADOUT_MENU, creatorData.IsDefaultLoadout ? msg("Creator.Title.DefaultLoadout", player.UserIDString) : msg("Creator.Title", player.UserIDString), 18, new UI4(0.02f, 0.775f, 0.99f, 0.975f), TextAnchor.MiddleLeft, UI.FontStyle.RobotoCondensedBold);
            UI.Button(ref container, UI_LOADOUT_MENU, ExitColor, "✘", 12, new UI4(0.92f, 0.8f, 0.985f, 0.955f), "loadoutcreator.setamount 0");
            UI.Panel(ref container, UI_LOADOUT_MENU, HeaderColor, new UI4(0.01f, 0.6f, 0.99f, 0.75f));
            UI.Label(ref container, UI_LOADOUT_MENU, string.Format("Set amount for item : {0}", ItemManager.itemDictionaryByName[shortname].displayName.english), 12, new UI4(0.02f, 0.60f, 0.99f, 0.75f), TextAnchor.MiddleLeft);
            //Input Field Fuckery
            UI.Panel(ref container, UI_LOADOUT_MENU, PanelColor, new UI4(0.01f, 0.025f, 0.99f, 0.6f));
            UI.Label(ref container, UI_LOADOUT_MENU, msg("Creator.Current", player.UserIDString), 12, new UI4(0.02f, 0.43f, 0.25f, 0.53f), TextAnchor.MiddleLeft);
            UI.Label(ref container, UI_LOADOUT_MENU, current.ToString(), 12, new UI4(0.175f, 0.43f, 0.9f, 0.53f), TextAnchor.MiddleLeft);
            UI.Label(ref container, UI_LOADOUT_MENU, msg("Creator.Max", player.UserIDString), 12, new UI4(0.02f, 0.31f, 0.25f, 0.41f), TextAnchor.MiddleLeft);
            UI.Label(ref container, UI_LOADOUT_MENU, max.ToString(), 12, new UI4(0.175f, 0.31f, 0.9f, 0.41f), TextAnchor.MiddleLeft);
            UI.Label(ref container, UI_LOADOUT_MENU, msg("Creator.Amount", player.UserIDString), 12, new UI4(0.02f, 0.15f, 0.25f, 0.3f), TextAnchor.MiddleLeft);
            UI.Panel(ref container, UI_LOADOUT_MENU, "0 0 0 0.7", new UI4(0.15f, 0.15f, 0.98f, 0.3f));
            UI.Input(ref container, UI_LOADOUT_MENU, string.Empty, 12, "loadoutcreator.setamount", new UI4(0.175f, 0.15f, 0.98f, 0.3f));
            CuiHelper.DestroyUi(player, UI_LOADOUT_MENU);
            CuiHelper.AddUi(player, container);
        }
#endregion
#region Item Selector Menu
        private void OpenItemSelectionMenu(BasePlayer player, ItemCategory category, ContainerType containerType, int slot) {
            CuiElementContainer container = UI.BlurContainer(UI_LOADOUT_MENU, new UI4(0.25f, 0.275f, 0.85f, 0.725f), BackgroundColor);
            // Header
            UI.Panel(ref container, UI_LOADOUT_MENU, PanelColor, new UI4(0.004f, 0.9f, 0.996f, 0.99f));
            UI.Label(ref container, UI_LOADOUT_MENU, msg("ItemSelector.Title", player.UserIDString), 18, new UI4(0.014f, 0.9f, 0.99f, 0.99f), TextAnchor.MiddleLeft, UI.FontStyle.RobotoCondensedBold);
            UI.Button(ref container, UI_LOADOUT_MENU, ExitColor, "✘", 12, new UI4(0.965f, 0.91f, 0.994f, 0.98f), "loadoutcreator.cancelitemselect");
            UI.Panel(ref container, UI_LOADOUT_MENU, PanelColor, new UI4(0.004f, 0.01f, 0.996f, 0.89f));
            UI.Panel(ref container, UI_LOADOUT_MENU, HeaderColor, new UI4(0.004f, 0.83f, 0.996f, 0.89f));
            if (containerType != ContainerType.Wear) {
                float width = Mathf.Min(0.994f / itemsByCategory.Count, 0.1f);
                for (int i = 0; i < itemsByCategory.Count; i++) {
                    ItemCategory itemCategory = itemsByCategory.Keys.ElementAt(i);
                    float x = 0.004f + (width * i);
                    UI4 pos = new UI4(x, 0.83f, x + width, 0.89f);
                    if (itemCategory == category) {
                        UI.Panel(ref container, UI_LOADOUT_MENU, "0 0 0 0.5", pos);
                        UI.Label(ref container, UI_LOADOUT_MENU, itemCategory.ToString(), 10, pos);
                    }
                    else UI.Button(ref container, UI_LOADOUT_MENU, COLOR_INVISIBLE, itemCategory.ToString(), 10, pos, $"loadoutcreator.changecategory {(int)itemCategory} {(int)containerType} {slot}");
                }
            }
            LayoutSelectorItems(ref container, UI_LOADOUT_MENU, containerType == ContainerType.Wear ? ItemCategory.Attire : category, containerType, slot, 1, 0.69f);
         
// ... [Code preview truncated due to length. Full source in attached file] ...

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