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

FREE VehicleTow : 1.0.9 1.0.9

Нет прав для скачивания
C#:
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using UnityEngine;
using Steamworks;
///Скачано с дискорд сервера Rust Edit [PRO+]
///discord.gg/9vyTXsJyKR
namespace Oxide.Plugins {
    [Info("Vehicle Towing", "discord.gg/9vyTXsJyKR", "1.0.9")]
    [Description("Allows towing of vehicles with cars.")]
    class VehicleTow : RustPlugin {
#region CONFIG
        private class MeAnchor {
            [JsonProperty("X")]
            public float X;
            [JsonProperty("Y")]
            public float Y;
            [JsonProperty("Width")]
            public float W;
            [JsonProperty("Height")]
            public float H;
        }
        private class NTF {
            public static class C {
                [JsonIgnore]
                public static string Red = "<color=#E77471>";
                [JsonIgnore]
                public static string ChRed = "<color=#C24641>";
                [JsonIgnore]
                public static string Green = "<color=#6AFB92>";
                [JsonIgnore]
                public static string Blue = "<color=#82CAFF>";
                [JsonIgnore]
                public static string Beige = "<color=#F5F5DC>";
            }
            public static void SendMessage(BasePlayer player, string input, Dictionary<string, string> replacements = null, bool all = false) {
                if (string.IsNullOrEmpty(input)) return;
                string output = replacements == null ? input : replacements.Aggregate(input, (current, replacement) => current.Replace(replacement.Key, replacement.Value));
                if (all) if (player != null) BasePlayer.activePlayerList.Where(pl => pl != player).ToList().ForEach(pl => pl.ChatMessage(output));
                else Instance.Server.Broadcast(output);
                else if (Instance.IsConn(player)) player?.ChatMessage(output);
            }
            [JsonProperty("Max Allowed Load - [name], [max]")]
            public string MaxAllow = $"{C.Blue}[name]</color> -> {C.Red}Max Allowed Load:</color> {C.ChRed}[max]</color>";
            [JsonProperty("Max Distance - [name], [current], [max], [marked]")]
            public string MaxDistance = $"{C.Blue}[name]</color> <- {C.Red}[current]m</color>/{C.Green}[max]m</color> -> {C.Blue}[marked]</color>";
            [JsonProperty("Set Behind - [name]")]
            public string SetBehind = $"{C.Blue}[name]</color> SET -> {C.Green}BEHIND</color>";
            [JsonProperty("Roof Block - [name]")]
            public string RoofBlock = $"{C.Blue}[name]</color> Placing onto Vehicle Roofs is {C.Red}Not Allowed</color>";
            [JsonProperty("Set On Top - [name]")]
            public string SetOnTop = $"{C.Blue}[name]</color> SET -> {C.Beige}ON TOP</color>";
            [JsonProperty("Not Vehicle - [name]")]
            public string NotVehicle = $"{C.Blue}[name]</color> -> {C.Red}Not Vehicle</color>";
            [JsonProperty("Invalid Vehicle - [name]")]
            public string InvlidVehicle = $"{C.Blue}[name]</color> -> {C.Red}Invalid Vehicle</color>";
            [JsonProperty("Vehicle Locked - [name]")]
            public string VehicleLocked = $"{C.Blue}[name]</color> -> {C.Red}Vehicle is Locked</color>";
            [JsonProperty("Vehicle Detached - [name]")]
            public string Detached = $"{C.Blue}[name]</color> -> {C.Green}DETACHED</color>";
            [JsonProperty("Vehicle Not Detachable - [name]")]
            public string NotDetachable = $"{C.Blue}[name]</color> -> {C.Red}Not Detachable</color>";
            [JsonProperty("Marked Vehicle - [name]")]
            public string Marked = $"{C.Blue}[name]</color> -> {C.Beige}MARKED</color>";
            [JsonProperty("Pickup Marked Vehicle - [name]")]
            public string PickupMarked = $"{C.Blue}[name]</color> -> {C.Beige}PICKUP MARKED</color>";
            [JsonProperty("Destroyed Vehicle - [name]")]
            public string Destroyed = $"{C.Blue}[name]</color> -> {C.Red}Destroyed</color>";
            [JsonProperty("Already Attached Vehicle - [name]")]
            public string AAttached = $"{C.Blue}[name]</color> -> {C.Red}Already attached</color>";
            [JsonProperty("Can't Attach Vehicle - [name], [marked]")]
            public string CantAttach = $"{C.Blue}[marked]</color> -> {C.Red}Can't be attached to</color> {C.Beige}[name]</color>";
            [JsonProperty("Chassis Created - [chassis]")]
            public string ChassisCr = $"{C.Blue}[chassis]</color> -> {C.Green}Created</color>";
            [JsonProperty("Can't Afford Item - [at], [need], [item], [have]")]
            public string CantAfford = $"|Option [at]| <color=#C24641>Can't Afford</color>: {C.Blue}x[need] [item]</color> -> {C.Red}Have x[have]</color>\n";
            [JsonProperty("Chassis Create Confirm")]
            public string ChassisConf = $"{C.Beige}Attach</color> -> Hit the ground 1 more time for chassis spawn";
            [JsonProperty("No Permissions")]
            public string NoPermissions = $"{C.Red}No Permission</color> to use this item!";
            [JsonProperty("Attach Cancelled")]
            public string AttachCanc = $"{C.Beige}Attach</color> -> {C.Red}Cancelled</color>";
            [JsonProperty("Invalid Ground Hit - [name]")]
            public string InvGround = $"{C.Blue}[name]</color> -> {C.Red}Not Ground</color>";
        }
        private Configuration Settings;
        private class Configuration {
            [JsonProperty("BEHIND - Max Vehicles")]
            public int MaxBehind;
            [JsonProperty("BEHIND - Max Distance for Attaching")]
            public float MaxBDist;
            [JsonProperty("ON TOP - Max Vehicles")]
            public int MaxTop;
            [JsonProperty("ON TOP - Max Distance for Attaching")]
            public float MaxOTDist;
            [JsonProperty("ON TOP - Allow Placing onto Vehicle Roofs")]
            public bool RoofTop;
            [JsonProperty("Max Tilt Angle before Detaching - Default 50")]
            public float MaxTilt;
            [JsonProperty("Hammer Skin - Default 833855159")]
            public ulong HmSKin;
            [JsonProperty("Locked Vehicles Requires Access")]
            public bool VhLock = true;
            [JsonProperty("Hammer Cost - shortName: ammount (Any Combination : EMPTY = FREE)")]
            public List<Dictionary<string, int>> HmCost;
            [JsonProperty("2 Module Chassis Cost - shortName: amount (Any Combination : EMPTY = FREE)")]
            public List<Dictionary<string, int>> MD2Cost;
            [JsonProperty("3 Module Chassis Cost - shortName: amount (Any Combination : EMPTY = FREE)")]
            public List<Dictionary<string, int>> MD3Cost;
            [JsonProperty("4 Module Chassis Cost - shortName: amount (Any Combination : EMPTY = FREE)")]
            public List<Dictionary<string, int>> MD4Cost;
            [JsonProperty("User Permissions - EMPTY = FREE")]
            public List<string> Perms;
            [JsonProperty("Item Images URL - Don't edit if you dont have a valid link")]
            public string imageURL;
            [JsonProperty("Tow Hammer Menu Anchor")]
            public MeAnchor THAnchor;
            [JsonProperty("Exclusion List - Forbidden Entities")]
            public List<string> Exclusion = new List<string>();
            [JsonProperty("Chassis Pickup Only Owner")]
            public bool ChassisOwner = true;
            [JsonProperty("Chassis Pickup Resources - shortName: amount")]
            public Dictionary<string, Dictionary<string, int>> ChassisRet = new Dictionary<string, Dictionary<string, int>>() {
                {
                    "car_chassis_2module.entity", new Dictionary<string, int>() {
                        {
                            "vehicle.chassis.2mod", 1
                        }
                    }
                }
                , {
                    "car_chassis_3module.entity", new Dictionary<string, int>() {
                        {
                            "vehicle.chassis.3mod", 1
                        }
                    }
                }
                , {
                    "car_chassis_4module.entity", new Dictionary<string, int>() {
                        {
                            "vehicle.chassis.4mod", 1
                        }
                    }
                }
            }
            ;
            [JsonProperty("Game Notifications - '' = disabled")]
            public NTF Ntf = new NTF();
            public static Configuration Generate() {
                return new Configuration {
                    MaxBehind = 3, MaxBDist = 5f, MaxTop = 3, MaxOTDist = 5f, RoofTop = true, MaxTilt = 50f, HmSKin = 833855159, HmCost = new List<Dictionary<string, int>>() {
                        new Dictionary<string, int>() {
                            {
                                "metal.fragments", 50
                            }
                            , {
                                "metalpipe", 1
                            }
                        }
                    }
                    , MD2Cost = new List<Dictionary<string, int>>() {
                        new Dictionary<string, int>() {
                            {
                                "piston1", 1
                            }
                            , {
                                "crankshaft1", 1
                            }
                        }
                        , new Dictionary<string, int>() {
                            {
                                "piston2", 1
                            }
                            , {
                                "crankshaft2", 1
                            }
                        }
                        , new Dictionary<string, int>() {
                            {
                                "piston3", 1
                            }
                            , {
                                "crankshaft3", 1
                            }
                        }
                    }
                    , MD3Cost = new List<Dictionary<string, int>>() {
                        new Dictionary<string, int>() {
                            {
                                "piston1", 2
                            }
                            , {
                                "crankshaft1", 1
                            }
                        }
                        , new Dictionary<string, int>() {
                            {
                                "piston2", 2
                            }
                            , {
                                "crankshaft2", 1
                            }
                        }
                        , new Dictionary<string, int>() {
                            {
                                "piston3", 2
                            }
                            , {
                                "crankshaft3", 1
                            }
                        }
                    }
                    , MD4Cost = new List<Dictionary<string, int>>() {
                        new Dictionary<string, int>() {
                            {
                                "piston1", 2
                            }
                            , {
                                "crankshaft1", 2
                            }
                        }
                        , new Dictionary<string, int>() {
                            {
                                "piston2", 2
                            }
                            , {
                                "crankshaft2", 2
                            }
                        }
                        , new Dictionary<string, int>() {
                            {
                                "piston3", 2
                            }
                            , {
                                "crankshaft3", 2
                            }
                        }
                    }
                    , Perms = new List<string>() {
                        "vehicletow.user"
                    }
                    , imageURL = "https://rustlabs.com/img/items180/{itemShortname}.png", THAnchor = new MeAnchor() {
                        X = 0.652f, Y = 0.026f, W = 0.1f, H = 0.05f
                    }
                }
                ;
            }
        }
        protected override void SaveConfig() => Config.WriteObject(Settings);
        protected override void LoadDefaultConfig() {
            Settings = Configuration.Generate();
            SaveConfig();
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                Settings = Config.ReadObject<Configuration>();
                if (Settings == null) LoadDefaultConfig();
                SaveConfig();
            }
            catch {
                PrintError("Error reading config, please check!");
            }
        }
#endregion
#region DATA
        [PluginReference]
        Plugin ImageLibrary;
        private const string _IName = "Tow Hammer";
        private readonly int _Mask = LayerMask.GetMask("Terrain", "World");
        private readonly string[] ChassisPrefabs = new string[3] {
            "assets/content/vehicles/modularcar/car_chassis_2module.entity.prefab", "assets/content/vehicles/modularcar/car_chassis_3module.entity.prefab", "assets/content/vehicles/modularcar/car_chassis_4module.entity.prefab"
        }
        ;
        private static readonly DamageTypeList _EmptyDmgList = new DamageTypeList();
        static VehicleTow Instance;
#endregion
#region UI
        class UI {
            public static Hash<string, string> ItemURLcache = new Hash<string, string>();
            public static readonly string[] PanelStatic = {
                "EngineMenu", "AttachMenu"
            }
            ;
            public static CuiElementContainer _cUIs = new CuiElementContainer();
            public static void Clean() {
                ItemURLcache.Clear();
                foreach (BasePlayer player in BasePlayer.activePlayerList) foreach (string Panel in PanelStatic) CuiHelper.DestroyUi(player, Panel);
            }
            public static string GetImage(int itemID, ulong skinID = 0) => GetImage(ItemManager.FindItemDefinition(itemID)?.shortname ?? "", skinID);
            public static string GetImage(string shortname, ulong skinID = 0) => GetItemIconURL(shortname, skinID);
            private static string GetItemIconURL(string shortname, ulong skinID = 0) {
                if (skinID != 0 && Instance.ImageLibrary != null) {
                    ItemURLcache[shortname] = Instance.ImageLibrary.Call<string>("GetImageURL", shortname, skinID);
                    if (string.IsNullOrEmpty(ItemURLcache[shortname])) ItemURLcache[shortname] = MakeURL(shortname);
                }
                else {
                    ItemURLcache[shortname] = MakeURL(shortname);
                }
                return ItemURLcache[shortname];
            }
            private static string MakeURL(string itemShortname) {
                string URL = Instance.Settings.imageURL;
                return URL.Replace("{itemShortname}", itemShortname);
            }
            static CuiRectTransformComponent Normalize(float[] XYWH, bool Linked) {
                CuiRectTransformComponent RectComp = new CuiRectTransformComponent();
                if (Linked) {
                    float x = XYWH[0], y = XYWH[1], w = XYWH[2], h = XYWH[3];
                    XYWH[0] = (1280f * x) - 1280f;
                    XYWH[1] = 720f * (y + h);
                    XYWH[2] = (1280f * (x + w)) - 1280f;
                    XYWH[3] = 720f * y;
                    RectComp = new CuiRectTransformComponent {
                        AnchorMin = "1 0", AnchorMax = "1 0", OffsetMin = $"{XYWH[0]} {XYWH[3]}", OffsetMax = $"{XYWH[2]} {XYWH[1]}"
                    }
                    ;
                }
                else {
                    XYWH[2] += XYWH[0];
                    XYWH[3] += XYWH[1];
                    RectComp = new CuiRectTransformComponent {
                        AnchorMin = $"{XYWH[0]} {XYWH[1]}", AnchorMax = $"{XYWH[2]} {XYWH[3]}"
                    }
                    ;
                }
                return RectComp;
            }
            public static CuiElementContainer CreateElementContainer(string panel, string color, float x, float y, float width, float height, bool cursor = false, bool blur = false, string parent = "Overlay", float fadein = 0.4f, bool Linked = false) {
                CuiRectTransformComponent RectComp = Normalize(new float[4] {
                    x, y, width, height
                }
                , Linked);
                CuiImageComponent img;
                if (blur) {
                    //assets/content/ui/uibackgroundblur.mat
                    img = new CuiImageComponent {
                        Color = color, FadeIn = fadein, Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat"
                    }
                    ;
                }
                else {
                    img = new CuiImageComponent {
                        Color = color, FadeIn = fadein
                    }
                    ;
                }
                CuiElementContainer NewElement = new CuiElementContainer() {
                    new CuiElement {
                        Name = panel, Parent = parent, Components = {
                            img, RectComp
                        }
                    }
                    , {
                        new CuiPanel {
                            CursorEnabled = cursor, Image = img
                        }
                        , panel, ""
                    }
                }
                ;
                return NewElement;
            }
            public static void CreatePanel(ref CuiElementContainer element, string panel, string color, float x, float y, float width, float height, string name = "", bool cursor = false, float fadein = 0.4f) {
                string aMin = x.ToString() + " " + y.ToString();
                string aMax = (x + width).ToString() + " " + (y + height).ToString();
                element.Add(new CuiPanel {
                    Image = {
                        Color = color, FadeIn = fadein
                    }
                    , RectTransform = {
                        AnchorMin = aMin, AnchorMax = aMax
                    }
                    , CursorEnabled = cursor
                }
                , panel, name);
            }
            public static void CreateLabel(ref CuiElementContainer element, string panel, string color, string text, int size, float x, float y, float width, float height, string name = "", TextAnchor align = TextAnchor.MiddleCenter, float fadein = 0.4f) {
                string aMin = x.ToString() + " " + y.ToString();
                string aMax = (x + width).ToString() + " " + (y + height).ToString();
                element.Add(new CuiLabel {
                    Text = {
                        Color = color, FontSize = size, Font = "RobotoCondensed-Regular.ttf", Align = align, FadeIn = fadein, Text = text
                    }
                    , RectTransform = {
                        AnchorMin = aMin, AnchorMax = aMax
                    }
                }
                , panel, name);
            }
            public static void CreateTextPanel(ref CuiElementContainer element, string panel, string color, string text, int size, float x, float y, float width, float height, string textColor, string name = "", TextAnchor align = TextAnchor.MiddleCenter, float fadein = 0.4f) {
                CreatePanel(ref element, panel, color, x, y, width, height, name, false, fadein);
                CreateLabel(ref element, panel, textColor, text, size, x, y, width, height, name, align);
            }
            public static void CreateButton(ref CuiElementContainer element, string panel, string color, string text, int size, float x, float y, float width, float height, string command, string tColor = "1 1 1 1", string name = "", TextAnchor align = TextAnchor.MiddleCenter, float fadein = 0.4f) {
                string aMin = x.ToString() + " " + y.ToString();
                string aMax = (x + width).ToString() + " " + (y + height).ToString();
                element.Add(new CuiButton {
                    Button = {
                        Color = color, Command = command, FadeIn = fadein
                    }
                    , RectTransform = {
                        AnchorMin = aMin, AnchorMax = aMax
                    }
                    , Text = {
                        Text = text, FontSize = size, Align = align, Color = tColor
                    }
                }
                , panel, name);
            }
            public static void CreateImgButton(ref CuiElementContainer element, string panel, string color, string text, int size, float x, float y, float width, float height, string command, string png, string name = "", string opacity = "1", string tColor = "1 1 1 1", TextAnchor align = TextAnchor.MiddleCenter) {
                string aMin = x.ToString() + " " + y.ToString();
                string aMax = (x + width).ToString() + " " + (y + height).ToString();
                element.Add(new CuiElement {
                    Name = name, Parent = panel, Components = {
                        new CuiRawImageComponent {
                            Url = png, Color = "1 1 1 " + opacity, FadeIn = 0.4f
                        }
                        , new CuiRectTransformComponent {
                            AnchorMin = aMin, AnchorMax = aMax
                        }
                    }
                }
                );
                element.Add(new CuiButton {
                    Button = {
                        Color = color, Command = command, FadeIn = 0.4f
                    }
                    , RectTransform = {
                        AnchorMin = aMin, AnchorMax = aMax
                    }
                    , Text = {
                        Text = text, FontSize = size, Align = align, Color = tColor
                    }
                }
                , panel, name);
            }
            public static void CreateImage(ref CuiElementContainer element, string panel, string png, float x, float y, float width, float height, string name = "", string opacity = "1", float fadein = 0.4f) {
                string aMin = x.ToString() + " " + y.ToString();
                string aMax = (x + width).ToString() + " " + (y + height).ToString();
                element.Add(new CuiElement {
                    Parent = panel, Components = {
                        new CuiRawImageComponent {
                            Url = png, Color = "1 1 1 " + opacity, FadeIn = fadein
                        }
                        , new CuiRectTransformComponent {
                            AnchorMin = aMin, AnchorMax = aMax
                        }
                        ,
                    }
                    , Name = name
                }
                );
            }
            public static void CreateTextImage(ref CuiElementContainer element, string panel, string png, float x, float y, float width, float height, string color, string text, int size, string name = "", string opacity = "1") {
                string aMin = x.ToString() + " " + y.ToString();
                string aMax = (x + width).ToString() + " " + (y + height).ToString();
                CuiElement imgCUI = new CuiElement {
                    Parent = panel, Components = {
                        new CuiRawImageComponent {
                            Url = png, Color = "1 1 1 " + opacity
                        }
                        , new CuiRectTransformComponent {
                            AnchorMin = aMin, AnchorMax = aMax
                        }
                        ,
                    }
                    , Name = name
                }
                ;
                element.Add(imgCUI);
                element.Add(new CuiLabel {
                    Text = {
                        Color = color, FontSize = size, Font = "RobotoCondensed-regular.ttf", Align = TextAnchor.LowerCenter, FadeIn = 0.4f, Text = text
                    }
                    , RectTransform = {
                        AnchorMin = aMin, AnchorMax = aMax
                    }
                }
                , imgCUI.Name);
            }
            public static string Color(string hexColor, float alpha) {
                if (hexColor.StartsWith("#")) hexColor = hexColor.TrimStart('#');
                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}";
            }
        }
        void SetupStatic() {
            // Engine UI
            CuiElementContainer _cUI = UI.CreateElementContainer(UI.PanelStatic[0], UI.Color("#808080", 0.1f), 0.652f, 0.32f, 0.047f, 0.08f, false, true, "Overlay", 0, true);
            UI.CreateImgButton(ref _cUI, UI.PanelStatic[0], UI.Color("#808080", 0), _IName, 10, 0.05f, 0.05f, 0.90f, 0.90f, "GiveTowHammer", UI.GetImage("hammer.salvaged", Instance.Settings.HmSKin), "", "1", UI.Color("#FFFFFF", 1), TextAnchor.LowerCenter);
            UI.CreatePanel(ref _cUI, UI.PanelStatic[0], UI.Color("#808080", 0), 1.05f, 0, 2, 1, "TowItemCost");
            float[] newPos = Instance.GetNewPosY(new float[] {
                0, 0.6f, 0, 0, 0.25f, 0.4f, 0.05f, 0.15f
            }
            );
            foreach (KeyValuePair<string, int> entry in Instance.Settings.HmCost[0]) {
                if (newPos == null) break;
                UI.CreateImage(ref _cUI, "TowItemCost", UI.GetImage(entry.Key), newPos[2], newPos[3], newPos[4], newPos[5]);
                UI.CreateLabel(ref _cUI, "TowItemCost", UI.Color("#FFFFFF", 1), $"x{entry.Value}", 10, newPos[2], newPos[3], newPos[4], newPos[5], "", TextAnchor.LowerRight);
                newPos = Instance.GetNewPosY(newPos);
            }
            UI._cUIs = _cUI;
        }
        void UpdateEngine(BasePlayer player) {
            CuiHelper.DestroyUi(player, UI.PanelStatic[0]);
            CuiHelper.AddUi(player, UI._cUIs);
        }
        void UpdateAttach(BasePlayer player) {
            CuiHelper.DestroyUi(player, UI.PanelStatic[1]);
            if (!WagonMonitor.plCreate.ContainsKey(player)) WagonMonitor.plCreate[player] = new Dictionary<int, int>() {
                {
                    0, 1
                }
            }
            ;
            MeAnchor A = Settings.THAnchor;
            CuiElementContainer _cUI = UI.CreateElementContainer(UI.PanelStatic[1], UI.Color("#808080", 0.1f), A.X, A.Y, A.W, A.H, false, true, "Overlay", 0, true);
            int id = WagonMonitor.plCreate[player].FirstOrDefault().Key;
            string[] chassis = new string[3] {
                "Small Chassis", "Medium Chassis", "Large Chassis"
            }
            ;
            UI.CreateLabel(ref _cUI, UI.PanelStatic[1], UI.Color("#FFFFFF", 1), $"{chassis[id]} [R]", 15, 0, 0, 1, 1);
            UI.CreatePanel(ref _cUI, UI.PanelStatic[1], UI.Color("#808080", 0), 0, 1.05f, 1, 2, "ChassisItemCost");
            List<Dictionary<string, int>> Data = id == 2 ? Instance.Settings.MD4Cost : id == 1 ? Instance.Settings.MD3Cost : Instance.Settings.MD2Cost;
            float[] newPos = Instance.GetNewPosY(new float[] {
                0.06f, 0.6f, 0, 0, 0.25f, 0.4f, 0.05f, 0.05f
            }
            );
            int at = 1;
            foreach (Dictionary<string, int> dict in Data) {
                foreach (KeyValuePair<string, int> entry in dict) {
                    if (newPos == null) break;
                    UI.CreateLabel(ref _cUI, "ChassisItemCost", UI.Color("#82CAFF", 1), $"{at}", 10, newPos[2], newPos[3], newPos[4], newPos[5], "", TextAnchor.UpperLeft);
                    UI.CreateImage(ref _cUI, "ChassisItemCost", UI.GetImage(entry.Key), newPos[2], newPos[3], newPos[4], newPos[5]);
                    UI.CreateLabel(ref _cUI, "ChassisItemCost", UI.Color("#FFFFFF", 1), $"x{entry.Value}", 10, newPos[2], newPos[3], newPos[4], newPos[5], "", TextAnchor.LowerRight);
                    newPos = Instance.GetNewPosY(newPos);
                }
                ++at;
            }
            CuiHelper.AddUi(player, _cUI);
        }
#endregion
#region CLASSES
        class WagonMonitor : MonoBehaviour {
            public static Dictionary<BaseEntity, BaseEntity> childParent = new Dictionary<BaseEntity, BaseEntity>();
            public static Dictionary<BasePlayer, BaseEntity> plSett = new Dictionary<BasePlayer, BaseEntity>();
            public static Dictionary<BasePlayer, BaseEntity> plPick = new Dictionary<BasePlayer, BaseEntity>();
            public static Dictionary<BasePlayer, Dictionary<int, int>> plCreate = new Dictionary<BasePlayer, Dictionary<int, int>>();
            static bool IsInvalid(ModularCar modular) => modular?.HasFlag(BaseEntity.Flags.Reserved6) ?? false;
            public static void CleanData(BasePlayer player) {
                if (plSett.ContainsKey(player)) plSett.Remove(player);
                if (plCreate.ContainsKey(player)) plCreate.Remove(player);
            }
            static BaseEntity getPlMark(BasePlayer player) => plSett.ContainsKey(player) ? plSett[player] : null;
            public static BaseEntity getPickMark(BasePlayer player) => plPick.ContainsKey(player) ? plPick[player] : null;
            static object[] getLastChild(BaseVehicle parent, BaseEntity child, bool chassis, BasePlayer player) {
                int atChild = 1;
                int atParent = 1;
                int debug = 100;
                int linked = 1;
                IEnumerable<BaseEntity> children = parent.children.Where(ch => chassis && ch is ModularCar || !chassis && !(ch is ModularCar) && ch is BaseVehicle);
                while (children.Count() > 0 && (debug -= 1) > 0) {
                    atChild++;
                    parent = children.LastOrDefault() as BaseVehicle;
                    children = parent.children.Where(ch => chassis && ch is ModularCar || !chassis && !(ch is ModularCar) && ch is BaseVehicle);
                }
                linked = atChild;
                int maxAtt = chassis ? Instance.Settings.MaxBehind : Instance.Settings.MaxTop;
                if (atChild <= maxAtt && chassis) {
                    debug = 100;
                    BaseEntity _parent = parent?.GetParentEntity();
                    while (_parent != null && (debug -= 1) > 0) {
                        atParent++;
                        _parent = _parent?.GetParentEntity();
                    }
                    linked = atParent;
                    if (atParent <= maxAtt) {
                        debug = 100;
                        atParent = 1 + (--atChild);
                        children = child.children.Where(ch => chassis && ch is ModularCar || !chassis && !(ch is ModularCar) && ch is BaseVehicle);
                        while (children.Count() > 0 && (debug -= 1) > 0) {
                            atParent++;
                            _parent = children.LastOrDefault() as BaseVehicle;
                            children = _parent.children.Where(ch => chassis && ch is ModularCar || !chassis && !(ch is ModularCar) && ch is BaseVehicle);
                        }
                        linked = atParent;
                    }
                }
                bool canAttach = atChild <= maxAtt && atParent <= maxAtt;
                if (!canAttach) {
                    string eName = parent.GetType().FullName;
                    NTF.SendMessage(player, Instance.Settings.Ntf.MaxAllow, new Dictionary<string, string>() {
                        {
                            "[name]", eName
                        }
                        , {
                            "[max]", maxAtt.ToString()
                        }
                    }
                    );
                    CleanData(player);
                    return new object[] {
                        null, linked
                    }
                    ;
                }
                return new object[] {
                    parent, linked
                }
                ;
            }
            static void TrySetChassis(BaseVehicle parent, BaseEntity child, BasePlayer player) {
                string eName = child.GetType().FullName;
                if (parent is ModularCar && child is ModularCar) {
                    object[] getLink = getLastChild(parent, child, true, player);
                    parent = getLink[0] as BaseVehicle;
                    if (parent.IsUnityNull()) return;
                    string eMark = parent.GetType().FullName;
                    float distance = Vector3.Distance(parent.transform.position, child.transform.position);
                    // Get Distance of Last Child
                    float alDist = Instance.Settings.MaxBDist;
                    if (distance > alDist) {
                        NTF.SendMessage(player, Instance.Settings.Ntf.MaxDistance, new Dictionary<string, string>() {
                            {
                                "[name]", eName
                            }
                            , {
                                "[current]", distance.ToString("0.00")
                            }
                            , {
                                "[max]", alDist.ToString()
                            }
                            , {
                                "[marked]", eMark
                            }
                        }
                        );
                        CleanData(player);
                        return;
                    }
                    child.gameObject.AddComponent<WagonMonitor>().Setup(parent, (int)getLink[1]);
                    NTF.SendMessage(player, Instance.Settings.Ntf.SetBehind, new Dictionary<string, string>() {
                        {
                            "[name]", eName
                        }
                    }
                    );
                }
                else {
                    if ((parent is ModularCar) && (parent as ModularCar).NumAttachedModules > 0 && !Instance.Settings.RoofTop) {
                        NTF.SendMessage(player, Instance.Settings.Ntf.RoofBlock, new Dictionary<string, string>() {
                            {
                                "[name]", eName
                            }
                        }
                        );
                        CleanData(player);
                        return;
                    }
                    float distance = Vector3.Distance(parent.transform.position, child.transform.position);
                    // Get Distance of Chassis
                    object[] getLink = getLastChild(parent, child, false, player);
                    parent = getLink[0] as BaseVehicle;
                    if (parent.IsUnityNull()) return;
                    string eMark = parent.GetType().FullName;
                    float alDist = Instance.Settings.MaxOTDist;
                    if (distance > alDist) {
                        NTF.SendMessage(player, Instance.Settings.Ntf.MaxDistance, new Dictionary<string, string>() {
                            {
                                "[name]", eName
                            }
                            , {
                                "[current]", distance.ToString("0.00")
                            }
                            , {
                                "[max]", alDist.ToString()
                            }
                            , {
                                "[marked]", eMark
                            }
                        }
                        );
                        CleanData(player);
                        return;
                    }
                    child.gameObject.AddComponent<WagonMonitor>().Setup(parent, (int)getLink[1], true);
                    NTF.SendMessage(player, Instance.Settings.Ntf.SetOnTop, new Dictionary<string, string>() {
                        {
                            "[name]", eName
                        }
                    }
                    );
                }
                CleanData(player);
                if (childParent.ContainsKey(child)) childParent.Remove(child);
                childParent.Add(child, parent);
            }
            public static void TrySetting(BasePlayer player, BaseEntity entity) {
                entity = entity?.GetParentEntity() != null && (!(entity is BaseVehicle) || entity is BaseVehicleModule) ? entity.GetParentEntity() : entity;
                string eName = entity.GetType().FullName;
                if (!(entity is BaseVehicle) || entity is BaseVehicleModule) {
                    NTF.SendMessage(player, Instance.Settings.Ntf.NotVehicle, new Dictionary<string, string>() {
                        {
                            "[name]", eName
                        }
                    }
                    );
                    return;
                }
                ModularCar modular = entity as ModularCar;
                if (IsInvalid(modular) || Instance.Settings.Exclusion.Contains(eName, StringComparer.OrdinalIgnoreCase)) {
                    NTF.SendMessage(player, Instance.Settings.Ntf.InvlidVehicle, new Dictionary<string, string>() {
                        {
                            "[name]", eName
                        }
                    }
                    );
                    return;
                }
                if (modular != null && Instance.Settings.VhLock && !modular.PlayerHasUnlockPermission(player)) {
                    NTF.SendMessage(player, Instance.Settings.Ntf.VehicleLocked, new Dictionary<string, string>() {
                        {
                            "[name]", eName
                        }
                    }
                    );
                    return;
                }
                if (plSett.ContainsKey(player) && plSett[player] == entity) {
                    bool detach = Instance.DetachEntity(entity);
                    string txt = detach ? Instance.Settings.Ntf.Detached : Instance.Settings.Ntf.NotDetachable ;
                    NTF.SendMessage(player, txt, new Dictionary<string, string>() {
                        {
                            "[name]", eName
                        }
                    }
                    );
                    CleanData(player);
                    return;
                }
                BaseEntity markedENT = getPlMark(player);
                if (!(markedENT is BaseEntity)) {
                    plSett[player] = entity;
                    NTF.SendMessage(player, Instance.Settings.Ntf.Marked, new Dictionary<string, string>() {
                        {
                            "[name]", eName
                        }
                    }
                    );
                    return;
                }
                string eMark = markedENT.GetType().FullName;
                if (markedENT.IsUnityNull() || markedENT.IsDestroyed) {
                    NTF.SendMessage(player, Instance.Settings.Ntf.Destroyed, new Dictionary<string, string>() {
                        {
                            "[name]", eName
                        }
                    }
                    );
                    CleanData(player);
                    return;
                }
                if (childParent.ContainsKey(markedENT) || childParent.ContainsKey(entity) && childParent[entity] == markedENT || childParent.ContainsKey(entity) && !(entity is ModularCar) && markedENT is ModularCar || entity == markedENT) {
                    NTF.SendMessage(player, Instance.Settings.Ntf.AAttached, new Dictionary<string, string>() {
                        {
                            "[name]", eName
                        }
                    }
                    );
                    CleanData(player);
                    return;
                }
                if (entity is ModularCar && markedENT is ModularCar || entity is ModularCar && markedENT is BaseVehicle) {
                    TrySetChassis((entity as BaseVehicle), markedENT, player);
                }
                else if (entity is BaseVehicle && markedENT is ModularCar) {
                    TrySetChassis((markedENT as BaseVehicle), entity, player);
                }
                else {
                    NTF.SendMessage(player, Instance.Settings.Ntf.CantAttach, new Dictionary<string, string>() {
                        {
                            "[name]", eName
                        }
                        , {
                            "[marked]", eMark
                        }
                    }
                    );
                    CleanData(player);
                    return;
                }
            }
            bool READY = false;
            bool onTop;
            float angularDrag;
            int links = 1;
            float updSpeed = 3f;
            float angleTilt = 50f;
            BaseEntity parent;
            ModularCar parentCar;
            BaseEntity child;
            ModularCar chassis;
            Rigidbody rigidbody;
            Vector3 local;
            Vector3 localElur => rigidbody.transform.eulerAngles;
            public float getAngDrag => angularDrag;
            float GetTop() {
                float Y = child is ScrapTransportHelicopter ? 2.85f : parent is ModularCar && (parent as ModularCar).NumAttachedModules <= 0 ? 0.85f : 0;
                return child.bounds.size.y - Y;
            }
            public void Setup(BaseEntity pr, int linked, bool top = false) {
                parent = pr;
                parentCar = pr as ModularCar;
                onTop = top;
                child = gameObject?.ToBaseEntity();
                angleTilt = Instance.Settings.MaxTilt;
                links = linked;
                if (onTop) {
                    local = Vector3.up * GetTop();
                    SetOnTop();
                }
                else if (child is ModularCar) {
                    chassis = child as ModularCar;
                    string name = chassis.ShortPrefabName;
                    float at = name.Contains("4module") ? child.bounds.size.z + 0.5f : name.Contains("3module") ? child.bounds.size.z + (parent.bounds.size.z / 3f) : child.bounds.size.z + (parent.bounds.size.z / 2f);
                    local = Vector3.back * at;
                    SetBehind();
                }
                Instance.NextTick(() => {
                    child.transform.parent = null;
                    child.transform.SetParent(parent.transform, true);
                }
                );
                READY = true;
            }
            void OnDestroy() {
                if (parent.IsUnityNull() || parent.IsDestroyed) {
                    GameManager.server.CreateEntity(child.PrefabName, child.transform.position, child.transform.rotation).Spawn();
                }
                childParent.Remove(child);
            }
            void SetOnTop() {
                transform.localPosition = local;
                child.SetParent(parent);
                rigidbody = GetComponent<Rigidbody>();
                angularDrag = rigidbody.angularDrag;
                rigidbody.transform.eulerAngles = new Vector3(0, parent.transform.eulerAngles.y, 0);
                rigidbody.constraints = RigidbodyConstraints.FreezePositionX | RigidbodyConstraints.FreezePositionZ | RigidbodyConstraints.FreezePositionY;
                rigidbody.angularDrag = 0;
            }
            void SetBehind() {
                transform.localPosition = local;
                child.SetParent(parent);
                rigidbody = GetComponent<Rigidbody>();
                angularDrag = rigidbody.angularDrag;
                rigidbody.transform.eulerAngles = new Vector3(localElur.x, parent.transform.eulerAngles.y, localElur.z);
                rigidbody.constraints = RigidbodyConstraints.FreezePositionX | RigidbodyConstraints.FreezePositionZ | RigidbodyConstraints.FreezeRotationY;
                rigidbody.angularDrag = 0;
            }
            float WrapAngle(float angle) {
                angle %= 360;
                if (angle > 180) return angle - 360;
                return angle;
            }
            bool IsTilted() {
                Vector3 eAngle = child.transform.rotation.eulerAngles;
                float angleX = WrapAngle(eAngle.x);
                float angleZ = WrapAngle(eAngle.z);
                return angleX > angleTilt || angleZ > angleTilt || angleX < -angleTilt || angleZ < -angleTilt;
            }
            void FixedUpdate() {
                if (parent.IsUnityNull() || parent.IsDestroyed) Destroy(this);
                if (!READY) return;
                if (IsTilted() || IsInvalid(chassis)) {
                    Instance.DetachEntity(child);
                    return;
                }
                if (onTop) {
                    transform.localPosition = local;
                    transform.rotation = Quaternion.Euler(new Vector3(localElur.x, parent.transform.eulerAngles.y, localElur.z));
                }
                else if (parentCar.IsMoving()) {
                    transform.localPosition = new Vector3(local.x, transform.localPosition.y, local.z);
                    Quaternion elur = Quaternion.Euler(new Vector3(localElur.x, parent.transform.eulerAngles.y, localElur.z));
                    float angle = Quaternion.Angle(transform.rotation, elur);
                    rigidbody.MoveRotation(Quaternion.RotateTowards(transform.rotation, elur, Time.deltaTime * updSpeed * angle));
                }
            }
        }
#endregion
#region METHODS
        bool DetachEntity(BaseEntity entity) {
            WagonMonitor monitor;
            if (!entity.TryGetComponent(out monitor)) return false;
            float angularDrag = monitor.getAngDrag;
            UnityEngine.Object.Destroy(monitor);
            Rigidbody rigidbody = entity.GetComponent<Rigidbody>();
            rigidbody.constraints = RigidbodyConstraints.None;
            rigidbody.angularDrag = angularDrag;
            entity.SetParent(null, true);
            if (WagonMonitor.childParent.ContainsKey(entity)) WagonMonitor.childParent.Remove(entity);
            return true;
        }
        void CreateChassis(BasePlayer player, V
// ... [Code preview truncated due to length. Full source in attached file] ...

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