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

FREE CarVendor : 1.2.1 1.2.1

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;
using Oxide.Game.Rust.Cui;
using Oxide.Core;
using Rust.Modular;

namespace Oxide.Plugins
{
    [Info("CarVendor", "senyaa", "1.2.1")]
    [Description("Adds a car vendor NPC")]
    public class CarVendor : RustPlugin 
    {
        #region Constants
        public const string SHOPKEEPER_PREFAB = "assets/prefabs/npc/bandit/shopkeepers/boat_shopkeeper.prefab";

        public const string SPAWNER_TRIGGER_PREFAB = "assets/prefabs/deployable/playerioents/gates/randswitch/electrical.random.switch.deployed.prefab";
        public const string SPAWNER_TRIGGER_CAT = "Car Vendor spawner";
        public const string MONUMENT_CAT = "Car Shop";
        public const string CAR_SPAWNPOINT_TRIGGER_PREFAB = "assets/prefabs/deployable/playerioents/gates/dflipflop/electrical.memorycell.deployed.prefab";
        public const string CAR_SPAWNPOINT_TRIGGER_CAT = "Car Spawnpoint";

        public const string BOLDTEXTCOLOR = "0.9686 0.9216 0.8824 0.5";
        public const string REGULARTEXTCOLOR = "0.9686 0.9215 0.8823 0.5235";
        public const string TRANSPARENT = "0 0 0 0";
        public const string RED = "0.8 0.28 0.2 1";
        public const string GREEN = "0.3647 0.4471 0.2235";
        public const string BG_COLOR = "0.1137 0.1059 0.0902 0.9";
        public const string DARK_GRAY = "0.3137 0.302 0.2824 1";
        public const string BLACK = "0.1686 0.1608 0.1412";

        public const BaseEntity.Flags CUSTOM_NPC_FLAG = BaseEntity.Flags.Reserved10;
        #endregion

        #region Fields
        public static CarVendor Instance;
        PluginConfig config;
        Dictionary<ulong, NPCTalking> LastTalkedTo;
        Dictionary<NPCTalking, PositionData> NPCVehicleSpawnpoints;
        Dictionary<ulong, DialogChoices> PlayerDialogChoices;
        Dictionary<ulong, PositionData> PlayerSpawnpoints;
        Dictionary<string, KeyValuePair<PositionData, PositionData>> ManuallyPlacedNPCs;

        List<BaseNetworkable> TriggerList;
        List<PositionData> SpawnerList;
        List<PositionData> SpawnpointList;

        ItemDefinition priceDef;
        #endregion

        #region Config
        class PluginConfig
        {
            [JsonProperty("(0) Price item short name")]
            public string Price_Item = "scrap";

            [JsonProperty("(1) Price of chassis/components")]
            public Dictionary<string, int> Price = new Dictionary<string, int>()
            {
                {"ComponentsTier0", 0 },
                {"ComponentsTier1", 50 },
                {"ComponentsTier2", 150 },
                {"ComponentsTier3", 200 },
                {"Chassis2", 75 },
                {"Chassis3", 150 },
                {"Chassis4", 175 }
            };
            [JsonProperty("(11) Discount permissions, must start with \"carvendor.\" (1.0 - full price, 0.75 - 25% price, etc.)")]
            public Dictionary<string, float> Discounts = new Dictionary<string, float>()
            {
                { "carvendor.discount50", 0.5f },
                { "carvendor.discount25", 0.75f }
            };

            [JsonProperty("(2) Car modules")]
            public Dictionary<int, string[]> Modules = new Dictionary<int, string[]>()
            {
                {2, new string[]
                {
                "vehicle.1mod.cockpit.with.engine",
                "vehicle.1mod.rear.seats"
                }},
                {3, new string[]
                {
                "vehicle.1mod.engine",
                "vehicle.1mod.cockpit.with.engine",
                "vehicle.1mod.rear.seats"
                }},
                {4, new string[]
                {
                "vehicle.1mod.engine",
                "vehicle.1mod.cockpit.armored",
                "vehicle.1mod.passengers.armored",
                "vehicle.1mod.engine"
                }},
            };

            [JsonProperty("(3) Spawn permission name")]
            public string Spawn_Permission_Name = "carvendor.spawn";

            [JsonProperty("(4) Car starting fuel")]
            public float Starting_Fuel = 75f;

            [JsonProperty("(5) Max distance between NPC and spawnpoint trigger (meters)")]
            public float Spawnpoint_Distance = 100f;

            [JsonProperty("(6) Check for other cars within radius (meters)")]
            public float Safe_Radius = 15f;

            [JsonProperty("(7) Nudge players (true/false)")]
            public bool Nudge_Players = true;

            [JsonProperty("(8) Player nudge radius (meters)")]
            public float Nudge_Radius = 5f;

            [JsonProperty("CUI Name")]
            public string UI_Name = "carvendor_ui";
        }
        protected override void LoadDefaultConfig() => Config.WriteObject(new PluginConfig(), true);
        #endregion

        #region Localization
        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>()
            {
                { "npc_name", "Car Vendor" },
                { "intro_content", "Hello there, is there anything I can help you with?" },
                { "intro_yes_btn", "I'm looking to buy a car" },
                { "intro_no_btn", "Nah, just looking around" },
                { "padbusy_content", "Hold up..There is a car, give me a minute to get them outta here." },
                { "padbusy_btn", "Okay." },
                { "purchase_complete_content", "Thanks for the purchase!\nYour car is behind you.Be sure to leave in the next 5 minutes or I'll have to repossess your purchase.\nNo refunds" },
                { "purchase_complete_btn", "Thanks." },
                { "tooMuch", "Whoa, that's way too much man, forget it" },
                { "pay", "PAY {0} [{1}]" },
                { "noComps", "No comps [FREE]" },
                { "sure", "Sure, that'll be {0} {1} please" },
                { "choose_components_dialog", "What tier of components do you want in your car?" },
                { "choose_chassis_dialog", "What did you have in mind?" },
                { "mc", "module chassis" },
                { "tier", "Tier" }
            }, this, "en");

            lang.RegisterMessages(new Dictionary<string, string>()
            {
                { "npc_name", "Автомеханик" },
                { "intro_content", "Привет, чем я могу тебе помочь?" },
                { "intro_yes_btn", "Я хочу купить машину" },
                { "intro_no_btn", "Ничем, просто осматриваюсь" },
                { "padbusy_content", "Подожди, там машина.Дай мне минутку, я их прогоню" },
                { "padbusy_btn", "Хорошо." },
                { "purchase_complete_content", "Спасибо за покупку!" },
                { "purchase_complete_btn", "Спасибо." },
                { "tooMuch", "Забей, это слишком много" },
                { "pay", "ЗАПЛАТИТЬ [{0} {1}]" },
                { "noComps", "БЕЗ КОМПОНЕНТОВ [БЕСПЛАТНО]" },
                { "sure", "С вас {0} {1}" },
                { "choose_components_dialog", "Какие компоненты хочешь?" },
                { "choose_chassis_dialog", "Что ты хотел?" },
                { "mc", "х модульная машина" },
                { "tier", "Уровень" }
            }, this, "ru");

        }
        #endregion

        #region Types
        public class PositionData
        {
            public Vector3 Position;
            public Vector3 Rotation;

            public PositionData(Vector3 position, Quaternion rotation)
            {
                Position = position;
                Rotation = rotation.eulerAngles;
            }
            [JsonConstructor]
            public PositionData(Vector3 position, Vector3 rotation)
            {
                Position = position;
                Rotation = rotation;
            }
        }
        public struct Dialog
        {
            [JsonProperty("(1) NPC Name")]
            public string NPC_Name;
            [JsonProperty("(2) Dialog text")]
            public string Text;
            [JsonProperty("(3) Dialog responses")]
            public DialogOption[] Options;
            [JsonProperty("(4) Response counter offset")]
            public int Counter_Offset;

            public Dialog(string NPC_Name, string Text, DialogOption[] Options, int Counter_Offset = 1)
            {
                this.NPC_Name = NPC_Name;   
                this.Text = Text;
                this.Options = Options;
                this.Counter_Offset = Counter_Offset;
            }
        }

        public struct DialogOption
        {
            [JsonProperty("(1) Response text")]
            public string Text;
            [JsonProperty("(2) Console command")]
            public string Command;

            public DialogOption(string Text, string Command = "carvendor.end")
            {
                this.Text = Text;
                this.Command = Command;
            }
        }

        public class DialogChoices
        {
            public int Chassis
            {
                get
                {
                    return _chassis;
                }
                set
                {
                    if (value >= 2 && value <= 4)
                        _chassis = value;
                    else
                        _chassis = 2;
                }
            }
            public int Components_Tier
            {
                get
                {
                    return _tier;
                }
                set
                {
                    if (value >= 0 && value <= 3)
                        _tier = value;
                    else

                        _tier = 1;
                }
            }

            private int _tier;
            private int _chassis;

            public DialogChoices()
            {
                _tier = 1;
                _chassis = 2;
            }

            public int CalculatePrice()
            {
                var result = 0;
                result += Instance.config.Price["ComponentsTier" + Components_Tier.ToString()];
                result += Instance.config.Price["Chassis" + Chassis.ToString()];
                return result;
            }

            public string GetPrefab() => $"assets/content/vehicles/modularcar/car_chassis_{Chassis}module.entity.prefab";
        }
        #endregion

        #region Hooks
        void Init()
        {
            Instance = this;
            LastTalkedTo = new Dictionary<ulong, NPCTalking>();
            NPCVehicleSpawnpoints = new Dictionary<NPCTalking, PositionData>();
            PlayerDialogChoices = new Dictionary<ulong, DialogChoices>();
            PlayerSpawnpoints = new Dictionary<ulong, PositionData>();
            SpawnerList = Facepunch.Pool.GetList<PositionData>();
            SpawnpointList = Facepunch.Pool.GetList<PositionData>();
            TriggerList = Facepunch.Pool.GetList<BaseNetworkable>();

            config = Config.ReadObject<PluginConfig>();

            permission.RegisterPermission(config.Spawn_Permission_Name, this);
            foreach (var perm in config.Discounts.Keys)
            {
                permission.RegisterPermission(perm, this);
            }

            try
            {
                priceDef = ItemManager.FindItemDefinition(config.Price_Item);
                if (priceDef == null)
                    throw new NullReferenceException();
            }
            catch (Exception)
            {
                PrintError("Item name is invalid! Players won't be charged for cars");
            }
        }

        void Unload()
        {
            var to_save = new Dictionary<int, PositionData>();

            foreach(var entry in NPCVehicleSpawnpoints)
                to_save.Add(entry.Key.GetInstanceID(), entry.Value);

            Interface.Oxide.DataFileSystem.WriteObject("CarVendor_CarSpawnpoints", to_save);

            LastTalkedTo = null;
            NPCVehicleSpawnpoints = null;
            PlayerDialogChoices = null;
            PlayerSpawnpoints = null;
            ManuallyPlacedNPCs = null;
            Instance = null;
        }

        object OnNpcConversationStart(NPCTalking npcTalking, BasePlayer player)
        {
            if (!npcTalking.HasFlag(CUSTOM_NPC_FLAG)) return null;

            if (LastTalkedTo.ContainsKey(player.userID))
                LastTalkedTo[player.userID] = npcTalking;
            else
                LastTalkedTo.Add(player.userID, npcTalking);

            if (!NPCVehicleSpawnpoints.ContainsKey(npcTalking))
                return null;

            var pos_data = NPCVehicleSpawnpoints[LastTalkedTo[player.userID]];

            npcTalking.ClientRPCPlayer(null, player, "Client_StartConversation", 0, "padbusy");

            ShowUI(player, !IsPadOccupied(pos_data.Position) ?  
                new Dialog(GetText("npc_name", player), GetText("intro_content", player),
                new DialogOption[]
                {
                    new DialogOption(GetText("intro_yes_btn", player), "carvendor.dialog choose_chassis"),
                    new DialogOption(GetText("intro_no_btn", player))
                })
                :
                new Dialog(GetText("npc_name", player), GetText("padbusy_content", player),
                new DialogOption[]
                {
                    new DialogOption(GetText("padbusy_btn", player))
                })); 
            return false;
        }

        void OnNpcConversationEnded(NPCTalking npcTalking, BasePlayer player)
        {
            if (!npcTalking.HasFlag(CUSTOM_NPC_FLAG)) return;

            EndDialog(player);
        }

        void OnWorldPrefabSpawned(GameObject gameObject, string category)
        {
            if ((category.Contains(SPAWNER_TRIGGER_CAT, System.Globalization.CompareOptions.IgnoreCase) && gameObject.name == SPAWNER_TRIGGER_PREFAB)
                || (category.Contains(MONUMENT_CAT, System.Globalization.CompareOptions.IgnoreCase) && gameObject.name == SPAWNER_TRIGGER_PREFAB))
            {
                var ent = gameObject.GetComponent<BaseNetworkable>();
                SpawnerList.Add(new PositionData(ent.transform.position, ent.transform.rotation));
                TriggerList.Add(ent);
                return;
            }

            if (category.Contains(CAR_SPAWNPOINT_TRIGGER_CAT, System.Globalization.CompareOptions.IgnoreCase) && gameObject.name == CAR_SPAWNPOINT_TRIGGER_PREFAB || 
                (category.Contains(MONUMENT_CAT, System.Globalization.CompareOptions.IgnoreCase) && gameObject.name == CAR_SPAWNPOINT_TRIGGER_PREFAB))
            {
                var ent = gameObject.GetComponent<BaseNetworkable>();
                SpawnpointList.Add(new PositionData(ent.transform.position, ent.transform.rotation));
                TriggerList.Add(ent);
            }
        }

        void OnServerInitialized(bool initial)
        {
            if (!initial)
            {
                Puts("Plugin hotloaded - Relinking");
                Facepunch.Pool.FreeList(ref SpawnerList);
                Facepunch.Pool.FreeList(ref SpawnpointList);
                
                var data = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<int, PositionData>>("CarVendor_CarSpawnpoints");
                var c = 0;

                foreach (var ent in BaseNetworkable.serverEntities)
                {
                    if (!(ent is NPCTalking)) continue; 
                    var ent_id = ent.GetInstanceID();

                    if (!data.ContainsKey(ent_id)) continue;
                    NPCVehicleSpawnpoints.Add(ent as NPCTalking, data[ent_id]);
                    c++;
                }

                LoadManuallyPlacedNPCs();
                
                Puts($"Relinked {c} spawnpoint(s) to NPC(s)");
                return;
            }

            LoadManuallyPlacedNPCs();

            var count = 0;

            foreach(var spawner in SpawnerList)
            {
                PositionData spawnpoint_ent = null;
                var minDist = config.Spawnpoint_Distance;
                foreach(var spawnpoint in SpawnpointList)
                {
                    var distance = Vector3.Distance(spawnpoint.Position, spawner.Position);
                    if(distance < minDist)
                    {
                        spawnpoint_ent = spawnpoint;
                        minDist = distance;
                    }
                }

                if(spawnpoint_ent == null)
                {
                    PrintError($"No car spawnpoint was found! Not spawning NPC...");
                    continue;
                }

                var npcs = Facepunch.Pool.GetList<NPCTalking>();

                Vis.Entities(spawner.Position, 0.3f, npcs);
                if (npcs.Count == 0)
                {
                    var npc = GameManager.server.CreateEntity(SHOPKEEPER_PREFAB, spawner.Position, Quaternion.Euler(spawner.Rotation)) as NPCTalking;
                    npc.Spawn();
                    NPCVehicleSpawnpoints.Add(npc, spawnpoint_ent);
                    npc.SetFlag(CUSTOM_NPC_FLAG, true, true);
                    npc.enableSaving = false;
                    count++;
                } 
                else
                {
                    foreach(var npc in npcs)
                    {
                        NPCVehicleSpawnpoints.Add(npc, spawnpoint_ent);
                        npc.SetFlag(CUSTOM_NPC_FLAG, true, true);
                        npc.enableSaving = false;
                        count++;
                    }
                }
                Facepunch.Pool.FreeList(ref npcs);
            } 

            Facepunch.Pool.FreeList(ref SpawnerList);
            Facepunch.Pool.FreeList(ref SpawnpointList);

            foreach(var trigger in TriggerList)
                if (!trigger.IsDestroyed)
                    trigger.Kill();

            Facepunch.Pool.FreeList(ref TriggerList);
        }
        #endregion

        #region Methods
        string GetText(string textName, BasePlayer player) => lang.GetMessage(textName, this, player?.UserIDString);

        void LoadManuallyPlacedNPCs()
        {
            ManuallyPlacedNPCs = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, KeyValuePair<PositionData, PositionData>>>("CarVendor_ManuallyPlacedNPCs");
            var i = 0;

            foreach (var npc_pos in ManuallyPlacedNPCs)
            {
                if (npc_pos.Key.StartsWith("MONUMENT"))
                {
                    var monumentName = npc_pos.Key.Split(':')[1];

                    foreach (var monument in TerrainMeta.Path.Monuments)
                    {
                        if (monument.name != monumentName) continue;
                        var spawnpoint = new PositionData(monument.transform.TransformPoint(npc_pos.Value.Value.Position), npc_pos.Value.Value.Rotation + monument.transform.rotation.eulerAngles);
                        SpawnNPC(monument.transform.TransformPoint(npc_pos.Value.Key.Position), Quaternion.Euler(npc_pos.Value.Key.Rotation + monument.transform.rotation.eulerAngles), spawnpoint);
                        i++;
                    }
                }
                else
                {
                    SpawnNPC(npc_pos.Value.Key.Position, Quaternion.Euler(npc_pos.Value.Key.Rotation), npc_pos.Value.Value);
                    i++;
                }
            }

            Puts($"Spawned {i} manually placed car vendor(s)");
        }

        void SpawnNPC(Vector3 position, Quaternion rotation, PositionData spawnpoint)
        {
            var npcs = Facepunch.Pool.GetList<NPCTalking>();
                
            Vis.Entities(position, 0.3f, npcs);
            if (npcs.Count == 0)
            {
                var vendor = GameManager.server.CreateEntity(SHOPKEEPER_PREFAB, position, rotation) as NPCTalking;
                vendor.Spawn();
                vendor.enableSaving = false;
                vendor.SetFlag(CUSTOM_NPC_FLAG, true, true);
                NPCVehicleSpawnpoints.Add(vendor, spawnpoint);
            }
            else 
            {
                foreach (var npc in npcs)
                {
                    npc.SetFlag(CUSTOM_NPC_FLAG, true, true);
                    if (!NPCVehicleSpawnpoints.ContainsKey(npc))
                        NPCVehicleSpawnpoints.Add(npc, spawnpoint);
                }
            }
            Facepunch.Pool.FreeList(ref npcs);
        }

        void EndDialog(BasePlayer player)
        {
            CuiHelper.DestroyUi(player, config.UI_Name);

            if (LastTalkedTo.ContainsKey(player.userID)) 
            {
                LastTalkedTo[player.userID].ClientRPCPlayer(null, player, "Client_EndConversation");
                LastTalkedTo.Remove(player.userID);
            }
            if (PlayerDialogChoices.ContainsKey(player.userID))
                PlayerDialogChoices.Remove(player.userID);
        }

        void AddModules(ModularCar car, string[] moduleNames)
        {
            for (int socketIndex = 0; socketIndex < moduleNames.Length; socketIndex++)
            {
                var desiredItem = moduleNames[socketIndex];

                var moduleItem = ItemManager.CreateByPartialName(desiredItem);
                if (moduleItem != null)
                    car.TryAddModule(moduleItem, socketIndex);
            }
        }

        void AddComponents(ModularCar car, int tier)
        {
            foreach (var module in car.AttachedModuleEntities)
            {
                var engineModule = module as VehicleModuleEngine;
                if (engineModule == null)
                    continue;

                var engineStorage = engineModule.GetContainer() as EngineStorage;

                if (engineStorage != null)
                {
                    var inventory = engineStorage.inventory;

                    for (var slot = 0; slot < inventory.capacity; slot++)
                    {
                        ItemModEngineItem output;
                        if (!engineStorage.allEngineItems.TryGetItem(tier, engineStorage.slotTypes[slot], out output))
                            break;

                        var component = output.GetComponent<ItemDefinition>();
                        var item = ItemManager.Create(component);
                        if (item == null)
                            break;
                        
                        if (!item.MoveToContainer(engineStorage.inventory, slot, allowStack: false))
                        {
                            item.Remove();
                            break;
                        }
                    }
                }
            }
        }
        
        void NudgePlayersInRadius(Vector3 spawnpoint, float radius)
        {
            var players = Facepunch.Pool.GetList<BasePlayer>();

            Vis.Entities(spawnpoint, radius, players, 131072, QueryTriggerInteraction.Collide);

            foreach (var player in players)
            {
                if (!player.IsNpc && !player.isMounted && player.IsConnected)
                {
                    var vector = spawnpoint;
                    vector += Vector3Ex.Direction2D(player.transform.position, spawnpoint) * radius;
                    vector += Vector3.up * 0.1f;
                    player.MovePosition(vector);
                    player.ClientRPCPlayer(null, player, "ForcePositionTo", vector);
                }
            }
            Facepunch.Pool.FreeList(ref players);
        }
        
	    BaseVehicle GetVehicleOccupying(Vector3 spawnpoint)
	    {
		    BaseVehicle result = null;
		    var vehicles = Facepunch.Pool.GetList<BaseVehicle>();
		    Vis.Entities(spawnpoint, 6f, vehicles, triggerInteraction: QueryTriggerInteraction.Ignore);
		    if (vehicles.Count > 0)
		    	result = vehicles[0];

		    Facepunch.Pool.FreeList(ref vehicles);
		    return result;
        }
        
        float GetDiscountMultiplier(BasePlayer player)
        {
            var minMultipler = 1f;

            foreach(var perm in permission.GetUserPermissions(player.UserIDString))
            {
                if (!perm.StartsWith("carvendor.")) continue;

                if (config.Discounts.ContainsKey(perm) && config.Discounts[perm] < minMultipler)
                    minMultipler = config.Discounts[perm];
            }
            return minMultipler;
        }

        bool IsPadOccupied(Vector3 spawnpoint) => GetVehicleOccupying(spawnpoint) != null;
        #endregion

        #region UI
        public void ShowUI(BasePlayer player, Dialog dialog) 
        {
            var container = new CuiElementContainer();

            container.Add(new CuiElement
            {
                Name = config.UI_Name,
                Parent = "Overlay",
                Components =
                {
                    new CuiImageComponent
                    {
                        Color = TRANSPARENT
                    },
                    new CuiRectTransformComponent
                    {
                        AnchorMin = "0.5 0.5",
                        AnchorMax = "0.5 0.5",
                        OffsetMin = "136 -122",
                        OffsetMax = "436 103"
                    }
                }
            });

            container.Add(new CuiElement
            {
                Name = $"{config.UI_Name}_vendor_name",
                Parent = config.UI_Name,
                Components =
                {
                    new CuiImageComponent
                    {
                        Color = DARK_GRAY,
                        Material = "assets/content/ui/uibackgroundblur.mat"
                    },
                    new CuiRectTransformComponent
                    {
                        AnchorMin = "0 1",
                        AnchorMax = "0 1",
                        OffsetMin = "10 -31",
                        OffsetMax = "111 -10"
                    }
                }
            });

            container.Add(new CuiElement
            {
                Name = $"{config.UI_Name}_vendor_name_text",
                Parent = $"{config.UI_Name}_vendor_name",
                Components =
                {
                    new CuiTextComponent
                    {
                        Text = dialog.NPC_Name,
                        Color = BOLDTEXTCOLOR,
                        FontSize = 12,
                        Align = TextAnchor.MiddleCenter
                    },
                    new CuiRectTransformComponent
                    {
                        AnchorMin = "0 0",
                        AnchorMax = "1 1"
                    }
                }
            });

            container.Add(new CuiElement
            {
                Name = $"{config.UI_Name}_textbox",
                Parent = config.UI_Name,
                Components =
                {
                    new CuiImageComponent
                    {
                        Color = DARK_GRAY,
                        Material = "assets/content/ui/uibackgroundblur.mat"
                    },
                    new CuiRectTransformComponent
                    {
                        AnchorMin = "0 1",
                        AnchorMax = "0 1",
                        OffsetMin = "10 -116",
                        OffsetMax = "290 -35"
                    }
                }
            });

            container.Add(new CuiElement
            {
                Name = $"{config.UI_Name}_textbox_text",
                Parent = config.UI_Name,
                Components =
                {
                    new CuiTextComponent
                    {
                        Font = "robotocondensed-regular.ttf",
                        Text = dialog.Text,
                        FontSize = 11,
                        Color = REGULARTEXTCOLOR,
                        Align = TextAnchor.UpperLeft
                    },
                    new CuiRectTransformComponent
                    {
                        AnchorMin = "0 1",
                        AnchorMax = "0 1",
                        OffsetMin = "17 -110",
                        OffsetMax = "288 -42"
                    }
                }
            });

            container.Add(new CuiElement
            {
                Name = $"{config.UI_Name}_close",
                Parent = config.UI_Name,
                Components = {
                    new CuiButtonComponent
                    {
                        Command = "carvendor.end",
                        Color = RED,
                    },
                    new CuiOutlineComponent
                    {
                        Color = BLACK,
                        Distance = "2.5 -2.5"
                    },
                    new CuiRectTransformComponent
                    {
                        AnchorMin = "1 1",
                        AnchorMax = "1 1",
                        OffsetMin = "-18 -18",
                        OffsetMax = "-2.5 -2.5",
                    }
                }
            });

            container.Add(new CuiElement
            {
                Name = $"{config.UI_Name}_close_text",
                Parent = $"{config.UI_Name}_close",
                Components =
                {
                    new CuiTextComponent
                    {
                        Text = "X",
                        Align = TextAnchor.MiddleCenter,
                        FontSize = 11,
                    },
                    new CuiRectTransformComponent
                    {
                        AnchorMin = "0 0",
                        AnchorMax = "1 1",
                        OffsetMin = "-1 0",
                        OffsetMax = "0 0"
                    },
                }
            });

            container.Add(new CuiElement
            {
                Name = $"{config.UI_Name}_dialogcontainer",
                Parent = config.UI_Name,
                Components =
                {
                    new CuiImageComponent
                    {
                        Color = TRANSPARENT
                    },
                    new CuiRectTransformComponent
                    {
                        AnchorMin = "0 1",
                        AnchorMax = "0 1",
                        OffsetMin = "10 -215",
                        OffsetMax = "291 -120"
                    }
                }
            });

            for (int i = 0; i < dialog.Options.Length; i++)
            {
                container.Add(new CuiElement
                {
                    Name = $"{config.UI_Name}_dialogcontainer_option_{i}",
                    Parent = $"{config.UI_Name}_dialogcontainer",
                    Components =
                    {
                        new CuiButtonComponent
                        {
                            Color = BLACK,
                            Material = "assets/content/ui/uibackgroundblur.mat",
                            Command = dialog.Options[i].Command
                        },
                        new CuiRectTransformComponent
                        {
                            AnchorMin = "0 1",
                            AnchorMax = "0 1",
                            OffsetMin = $"0 {-25 * (i + 1) + 5}",
                            OffsetMax = $"281 {-25 * i}"
                        }
                    }
                });

                container.Add(new CuiElement
                {
                    Name = $"{config.UI_Name}_dialogcontainer_option_{i}_label",
                    Parent = $"{config.UI_Name}_dialogcontainer_option_{i}",
                    Components =
                    {
                        new CuiTextComponent
                        {
                            Text = dialog.Options[i].Text,
                            Align = TextAnchor.MiddleLeft,
                            Font = "robotocondensed-regular.ttf",
                            Color = REGULARTEXTCOLOR,
                            FontSize = 11
                        },
                        new CuiRectTransformComponent
                        {
                            AnchorMin = "0 1",
                            AnchorMax = "0 1",
                            OffsetMin = "28 -21",
                            OffsetMax = "282 0"
                        }
                    }
                });

                container.Add(new CuiElement
                {
                    Name = $"{config.UI_Name}_dialogcontainer_option_{i}_index",
                    Parent = $"{config.UI_Name}_dialogcontainer_option_{i}",
                    Components =
                    {
                        new CuiImageComponent
                        {
                            Color = GREEN,
                            Material = "assets/content/ui/uibackgroundblur.mat"
                        },
                        new CuiRectTransformComponent
                        {
                            AnchorMin = "0 1",
                            AnchorMax = "0 1",
                            OffsetMin = "5 -17",
                            OffsetMax = "20 -2"
                        }
                    }
                });

                container.Add(new CuiElement
                {
                    Name = $"{config.UI_Name}_dialogcontainer_option_{i}_index_label",
                    Parent = $"{config.UI_Name}_dialogcontainer_option_{i}_index",
                    Components =
                    {
                        new CuiTextComponent
                        {
                            Text = (i + dialog.Counter_Offset).ToString(),
                            Color = BOLDTEXTCOLOR,
                            FontSize = 12,
                            Align = TextAnchor.MiddleCenter
                        },
                        new CuiRectTransformComponent
                        {
                            AnchorMin = "0 0",
                            AnchorMax = "1 1"
                        }
                    }
                });
            }
            CuiHelper.DestroyUi(player, config.UI_Name);
            CuiHelper.AddUi(player, container);;
        }
        #endregion

        #region Console Commands
        [ConsoleCommand("carvendor.end")]
        void EndDialogCCmd(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null) return;
            EndDialog(player);
        }

        [ConsoleCommand("carvendor.dialog")]
        void CarDialogCCmd(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            var args = arg.Args;

            if(player == null) return;
            if (!LastTalkedTo.ContainsKey(player.userID)) return;
            if (args.Length < 1) return;
            if (args[0] == "intro") return;

            if(args.Length == 2)
            {
                if (!PlayerDialogChoices.ContainsKey(player.userID))
                    PlayerDialogChoices.Add(player.userID, new DialogChoices());

                if (args[0] == "choose_components" && (args.Length == 2 || args[1].IsNumeric()))
                    PlayerDialogChoices[player.userID].Chassis = Convert.ToInt32(args[1]);
                else if (args[0] == "confirmation" && (args.Length == 2 || args[1].IsNumeric()))
                    PlayerDialogChoices[player.userID].Components_Tier = Convert.ToInt32(args[1]);
            }

            switch(args[0])
            {
                case "choose_chassis":
                    ShowUI(player, new Dialog(GetText("npc_name", player), GetText("choose_chassis_dialog", player),
                    new DialogOption[]
                    {
                        new DialogOption($"2 {GetText("mc", player)} [{Mathf.RoundToInt(config.Price["Chassis2"] * GetDiscountMultiplier(player))} {priceDef.displayName.english.ToUpper()}]", "carvendor.dialog choose_components 2"),
                        new DialogOption($"3 {GetText("mc", player)} [{Mathf.RoundToInt(config.Price["Chassis3"] * GetDiscountMultiplier(player))} {priceDef.displayName.english.ToUpper()}]", "carvendor.dialog choose_components 3"),
                        new DialogOption($"4 {GetText("mc", player)} [{Mathf.RoundToInt(config.Price["Chassis4"] * GetDiscountMultiplier(player))} {priceDef.displayName.english.ToUpper()}]", "carvendor.dialog choose_components 4"),
                    }, 2));
                    return;
                case "choose_components":
                    ShowUI(player, new Dialog(GetText("npc_name", player), GetText("choose_components_dialog", player),
                        new DialogOption[]
                        {
                            new DialogOption($"{GetText("tier", player)} 1 [{Mathf.RoundToInt(config.Price["ComponentsTier1"] * GetDiscountMultiplier(player))} {priceDef.displayName.english.ToUpper()}]", "carvendor.dialog confirmation 1"),
                            new DialogOption($"{GetText("tier", player)} 2 [{Mathf.RoundToInt(config.Price["ComponentsTier2"] * GetDiscountMultiplier(player))} {priceDef.displayName.english.ToUpper()}]", "carvendor.dialog confirmation 2"),
                            new DialogOption($"{GetText("tier", player)} 3 [{Mathf.RoundToInt(config.Price["ComponentsTier3"] * GetDiscountMultiplier(player))} {priceDef.displayName.english.ToUpper()}]", "carvendor.dialog confirmation 3"),
                            new DialogOption(GetText("noComps", player), "carvendor.dialog confirmation 0"),
                        }));
                    return;
                case "confirmation":
                    if (!PlayerDialogChoices.ContainsKey(player.userID))
                    {
                        EndDialog(player);
                        return;
                    }

                    var price = Mathf.RoundToInt(PlayerDialogChoices[player.userID].CalculatePrice() * GetDiscountMultiplier(player));
                    var able_to_pay = player.inventory.GetAmount(priceDef.itemid) >= price;

                    var dialog = new Dialog(GetText("npc_name", player), string.Format(GetText("sure", player), price, priceDef.displayName.english.ToLower()),
                    able_to_pay ?
                    new DialogOption[]
                    {
                        new DialogOption(string.Format(GetText("pay", player), price, priceDef.displayName.english.ToUpper()), "carvendor.dialog purchase"),
                        new DialogOption(GetText("tooMuch", player))
                    } 
                    :
                    new DialogOption[]
                    {
                        new DialogOption(GetText("tooMuch", player))
                    });
                    ShowUI(player, dialog);
                    return;
                case "purchase":
                    if (!PlayerDialogChoices.ContainsKey(player.userID))
                    {
                        EndDialog(player);
                        return;
                    }

                    var dialogChoices = PlayerDialogChoices[player.userID];

                    var final_price = Mathf.RoundToInt(dialogChoices.CalculatePrice() * GetDiscountMultiplier(player));

                    if(!(player.inventory.GetAmount(priceDef.itemid) >= final_price))
                    {
                        EndDialog(player);
                        return;
                    }

                    player.inventory.Take(null, priceDef.itemid, final_price);

                    var pos_data = NPCVehicleSpawnpoints[LastTalkedTo[player.userID]];
                    var car = GameManager.server.CreateEntity(dialogChoices.GetPrefab(), pos_data.Position, Quaternion.Euler(pos_data.Rotation)) as ModularCar;
                    
                    if(config.Nudge_Players)
                        NudgePlayersInRadius(pos_data.Position, config.Nudge_Radius);

                    car.Spawn();
        
                    ShowUI(player,  new Dialog(GetText("npc_name", player),
                        GetText("purchase_complete_content", player),
                    new DialogOption[]
                    {
                        new DialogOption(GetText("purchase_complete_btn", player))
                    }));
                    

                    AddModules(car, config.Modules[dialogChoices.Chassis]);

                    if (config.Starting_Fuel > 0) 
                    {
                        var fuelSystem = car.GetFuelSystem();
                        fuelSystem.AddStartingFuel(config.Starting_Fuel);
                    }

                    if (dialogChoices.Components_Tier > 0)
                    {
                        NextFrame(() =>
                        {
                            AddComponents(car, dialogChoices.Components_Tier);
                            car.SetupOwner(player, pos_data.Position, config.Safe_Radius);
                            car.OwnerID = player.userID;
                        });
                    }
                    return;
            }
        }
        #endregion

        #region Chat Commands
        [ChatCommand("carvendor")]
        void CarVendorCommand(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, config.Spawn_Permission_Name))
            {
                PrintToChat(player, "You don't have permission to run this command!");
                return;
            }
            
            if (args.Length == 0)
            {
                PrintToChat(player, "Usage: /carvendor npc_spawn/set_car_spawnpoint/reset");
                return;
            }

            switch (args[0])
            {
                case "npc_spawn":
                    if(!PlayerSpawnpoints.ContainsKey(player.userID))
                    {
                        PrintToChat(player, "You need to set a car spawnpoint.\nRun /carvendor set_car_spawnpoint");
                        return;
                    }

                    var playerRotation = Quaternion.Euler(0, player.eyes.GetLookRotation().eulerAngles.y, 0);

                    var vendor = GameManager.server.CreateEntity(SHOPKEEPER_PREFAB, player.transform.position, playerRotation) as NPCTalking;
                    vendor.Spawn();
                    vendor.enableSaving = false;
                    vendor.SetFlag(CUSTOM_NPC_FLAG, true, true);

                    NPCVehicleSpawnpoints.Add(vendor, PlayerSpawnpoints[player.userID]);

                    var alreadySpawned = false;

                    foreach (var monument in TerrainMeta.Path.Monuments)
                    {
                        if (Vector3.Distance(player.transform.position, monument.transform.position) < monument.Bounds.size.x)
                        {
                            var playerPosition = new PositionData(monument.transform.InverseTransformPoint(player.transform.position), player.viewAngles - monument.transform.rotation.eulerAngles);
;
                            var spawnpoint = new PositionData(monument.transform.InverseTransformPoint(PlayerSpawnpoints[player.userID].Position), PlayerSpawnpoints[player.userID].Rotation - monument.transform.rotation.eulerAngles);
                            ManuallyPlacedNPCs.Add($"MONUMENT:{monument.name}:{Guid.NewGuid()}", new KeyValuePair<PositionData, PositionData>(playerPosition, spawnpoint));
                            PrintToChat(player, $"You are on a monument! Saving positions relative to that monument");
                            alreadySpawned = true;
                            break;
                        }
                    }

                    if (!alreadySpawned)
                        ManuallyPlacedNPCs.Add(Guid.NewGuid().ToString(), new KeyValuePair<PositionData, PositionData>(new PositionData(player.transform.position, playerRotation.eulerAngles), PlayerSpawnpoints[player.userID]));

                    PlayerSpawnpoints.Remove(player.userID);

                    Interface.Oxide.DataFileSystem.WriteObject("CarVendor_ManuallyPlacedNPCs", ManuallyPlacedNPCs);

                    PrintToChat(player, "Car vendor spawned");
                    break;
                case "set_car_spawnpoint":
                    var data = new PositionData(player.transform.position, player.eyes.GetLookRotation().eulerAngles);
                    if (PlayerSpawnpoints.ContainsKey(player.userID))
                        PlayerSpawnpoints[player.userID] = data;
                    else
                        PlayerSpawnpoints.Add(player.userID, data);
                    PrintToChat(player, "Car spawnpoint set.\nNow run /carvendor npc_spawn to spawn the NPC");
                    break;
                case "reset":
                    foreach(var npc_pos in ManuallyPlacedNPCs)
                    {
                        var npcs = Facepunch.Pool.GetList<NPCTalking>();
                        Vis.Entities(npc_pos.Value.Key.Position, 0.3f, npcs);

                        foreach(var npc in npcs)
                        {
                            if (NPCVehicleSpawnpoints.ContainsKey(npc))
                                NPCVehicleSpawnpoints.Remove(npc);
                            if (!npc.IsDestroyed)
                                npc.Kill();
                        }
                        Facepunch.Pool.FreeList(ref npcs);
                    }
                    ManuallyPlacedNPCs = new Dictionary<string, KeyValuePair<PositionData, PositionData>>();
                    Interface.Oxide.DataFileSystem.WriteObject("CarVendor_ManuallyPlacedNPCs", ManuallyPlacedNPCs);
                    PrintToChat(player, "All car vendors are removed!");
                    break;
                default:
                    PrintToChat(player, "Usage: /carvendor npc_spawn/set_car_spawnpoint/reset");
                    break;
            }
        }
        #endregion
    }
}

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

Другие ресурсы пользователя 15FPS

Сверху