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

FREE CopterTaxi : 1.2.1 1.2.1

Нет прав для скачивания
C#:
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using Rust;
using System.Linq;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using Oxide.Core;
using ProtoBuf;
namespace Oxide.Plugins {
    [Info("CopterTaxi", "Qbis", "1.2.1")]
    public class CopterTaxi : RustPlugin {
#region [Vars]
        [PluginReference]
        Plugin ImageLibrary, Economics, IQEconomic, ServerRewards;
        private static CopterTaxi plugin;
        private List<ScrapTransportHelicopter> Copters = new List<ScrapTransportHelicopter>();
        private Dictionary<ulong, int> playersLastCall = new Dictionary<ulong, int>();
        private List<Vector3> SpawnsComp = new List<Vector3>() {
            new Vector3(13.2f, 11.1f, 3.0f), new Vector3(17.2f, 0.3f, -29.7f), new Vector3(-45.7f, 0.3f, -70.7f), new Vector3(50.7f, 0.3f, 57.7f)
        }
        ;
        private List<Vector3> SpawnsBandit = new List<Vector3>() {
            new Vector3(45.2f, 15.1f, -20.0f), new Vector3(-15.2f, 5.1f, 5.0f), new Vector3(55.2f, 11.1f, 18.0f), new Vector3(13.2f, 11.1f, 63.0f)
        }
        ;
#endregion
#region [Config]
        private PluginConfig config;
        protected override void LoadDefaultConfig() {
            config = PluginConfig.DefaultConfig();
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            config = Config.ReadObject<PluginConfig>();
            if (config.PluginVersion < Version) UpdateConfigValues();
            Config.WriteObject(config, true);
        }
        private void UpdateConfigValues() {
            PluginConfig baseConfig = PluginConfig.DefaultConfig();
            if (config.PluginVersion < Version) {
                PrintWarning("Plugin update detected! Checking config values...");
                if (Version == new VersionNumber(1, 0, 5)) {
                    config.taxi.copterFly = 80f;
                }
                if (Version == new VersionNumber(1, 2, 0)) {
                    config.taxi.monument = "compound";
                }
                config.PluginVersion = Version;
                PrintWarning("Config checked completed!");
            }
            config.PluginVersion = Version;
        }
        protected override void SaveConfig() {
            Config.WriteObject(config);
        }
        private class PluginConfig {
            [JsonProperty("Настройки такси")]
            public TaxiSettings taxi;
            [JsonProperty("Настройки стоимости такси")]
            public PriceSettings price;
            [JsonProperty("Настройка UI")]
            public UiSettings ui;
            [JsonProperty("Версия конфига")]
            public VersionNumber PluginVersion = new VersionNumber();
            public static PluginConfig DefaultConfig() {
                return new PluginConfig() {
                    taxi = new TaxiSettings() {
                        name = "Виталя", clothes = new Dictionary<string, ulong> {
                            ["hat.cap"]
                            = 2275597860, ["tshirt"] = 2442749397, ["pants"] = 2346785436, ["shoes.boots"] = 1427198029
                        }
                        , copterCount = 4, copterSpeed = 2f, copterFly = 80f, copterSpeedUp = 0.2f, copterSpeedLow = 0.5f, copterCallAgain = 600, copterWaitPay = 300, chatIcon = 76561198976168730, monument = "compound", permmission = "coptertaxi.use", discount = new Dictionary<string, int>() {
                            ["coptertaxi.discount10"]
                            = 10, ["coptertaxi.discount20"] = 20, ["coptertaxi.discount30"] = 30
                        }
                    }
                    , price = new PriceSettings() {
                        type = "Item", Cost = 100, shortname = "scrap", skinID = 0, url = "https://i.imgur.com/jBaVKHu.png"
                    }
                    , ui = new UiSettings() {
                        colorBG = "0 0 0 0.3", colorLines = "1.00 0.64 0.28 1.00", colorButtonPay = "0.09 0.39 0.14 0.85", colorButtonReturn = "0.39 0.09 0.14 0.85", colorButtonCall = "1.00 0.75 0.50 0.5", photoUrl = "https://i.imgur.com/tgSooQl.png"
                    }
                    , PluginVersion = new VersionNumber()
                }
                ;
            }
        }
        public class TaxiSettings {
            [JsonProperty("Имя для таксиста")]
            public string name;
            [JsonProperty("Одежда таксиста")]
            public Dictionary<string, ulong> clothes;
            [JsonProperty("Сколько создавать такси (от 1 до 4)")]
            public int copterCount;
            [JsonProperty("Высота полета такси (от 80 до 150) (менять с осторожностью!)")]
            public float copterFly;
            [JsonProperty("Скорость полета такси (менять с осторожностью!)")]
            public float copterSpeed;
            [JsonProperty("Скорость ускорения полета такси (менять с осторожностью!)")]
            public float copterSpeedUp;
            [JsonProperty("Скорость замедления полета такси (менять с осторожностью!)")]
            public float copterSpeedLow;
            [JsonProperty("Сколько ждет таксист для назначения маршрута игроком (в секундах)")]
            public int copterWaitPay;
            [JsonProperty("Как часто игрок может вызывать такси(в секундах)")]
            public int copterCallAgain;
            [JsonProperty("Привилегия для использования такси")]
            public string permmission;
            [JsonProperty("Привилегии для скидки")]
            public Dictionary<string, int> discount;
            [JsonProperty("Аватар для оповещения в чате (steamID)")]
            public ulong chatIcon;
            [JsonProperty("Выбор города для спавна такси (compound, bandit_town)")]
            public string monument;
        }
        public class PriceSettings {
            [JsonProperty("Тип оплаты для такси Item, CustomItem, Economics, IQEconomic, ServerRewards")]
            public string type;
            [JsonProperty("Стоимость 1км")]
            public int Cost;
            [JsonProperty("ShortName предмета (для Item, CustomItem)")]
            public string shortname;
            [JsonProperty("SkinID предмета (для CustomItem)")]
            public ulong skinID;
            [JsonProperty("Ссылка на картинку предмета/валюты  (кроме Item)")]
            public string url;
        }
        public class UiSettings {
            [JsonProperty("Цвет фона")]
            public string colorBG;
            [JsonProperty("Цвет обводки")]
            public string colorLines;
            [JsonProperty("Ссылка на логотип")]
            public string photoUrl;
            [JsonProperty("Цвет кнопки 'Вызвать'")]
            public string colorButtonCall;
            [JsonProperty("Цвет кнопки 'Оплатить'")]
            public string colorButtonPay;
            [JsonProperty("Цвет кнопки 'Отказаться'")]
            public string colorButtonReturn;
        }
#endregion
#region Localization⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠
        protected override void LoadDefaultMessages() {
            lang.RegisterMessages(new Dictionary<string, string> {
                ["AlreadyCall"]
                = "You have already been allocated a taxi!", ["Cant"] = "There is an obstacle for landing in this place, choose another point!", ["Near"] = "To fly too close, and you can walk!", ["NoBuild1"] = "A taxi will soon sit in this place, construction is prohibited at times!", ["NoBuild2"] = "Building next to a taxi is prohibited!", ["NoPerm"] = "You don't have access to call a taxi!", ["Distance"] = "Remaining: {0}km", ["Marker"] = "Waiting for a marker: {0}m.{1}s.", ["Nofunds"] = "You don't have enough funds", ["Say1"] = "<color=orange>{0}</color>: Hello, put a point on the map where to take you!", ["Say2"] = "<color=orange>{0}</color>: Bye!", ["Say3"] = "<color=orange>{0}</color>: Hello, I'm here! I ask you to board.", ["Say4"] = "<color=orange>{0}</color>: I warm up the engine and fly to you!", ["Say5"] = "<color=orange>{0}</color>: Fasten your seat belts, we take off!", ["UI_Header"] = "Vitala-Taxi LLC", ["UI_Text"] = "Tired of wasting resources? So call Vital!\nWe will deliver with comfort and a solid fart!", ["UI_Cost"] = "for 1 km | Discount {0}%", ["UI_Cost2"] = "flight cost | Distance {0} km | Discount {1}%", ["UI_Call"] = "A taxi call will be available in {0}h.{1}m.{2}s.", ["UI_NoCall"] = "There are no available taxis at the moment, please try again later", ["UI_Call2"] = "Call", ["UI_Pay"] = "Pay", ["UI_Close"] = "Close", ["UI_Refuse"] = "Refuse", ["UI_Free"] = "Free"
            }
            , this);
            lang.RegisterMessages(new Dictionary<string, string> {
                ["AlreadyCall"]
                = "Вам уже выделено такси!", ["Cant"] = "В этом месте есть помехи для посадки, выберите другую точку!", ["Near"] = "Слишком близко лететь, можно и пешочком!", ["NoBuild1"] = "В этом месте скоро сядет такси, постройка времена запрещена!", ["NoBuild2"] = "Постройка рядом с такси запрещена!", ["NoPerm"] = "У вас нет доступа для вызова такси!", ["Distance"] = "Осталось: {0}км", ["Marker"] = "Ожидание маркера: {0}м.{1}с.", ["Nofunds"] = "У вас недостаточно средств!", ["Say1"] = "<color=orange>{0}</color>: Здравствуйте, поставьте точку на карте, куда Вас подвезти!", ["Say2"] = "<color=orange>{0}</color>: До свидания!", ["Say3"] = "<color=orange>{0}</color>: Здравствуйте, я на месте! Прошу Вас на борт.", ["Say4"] = "<color=orange>{0}</color>: Прогреваю двигатель и вылетаю к Вам!", ["Say5"] = "<color=orange>{0}</color>: Пристегнуть ремни, мы взлетаем!", ["UI_Header"] = "ООО Виталя-Такси", ["UI_Text"] = "Устал просирать ресурсы? Так вызови Виталю!\nДоставим с комфортом и цельным пуканом!", ["UI_Cost"] = "за 1 км | Скидка {0}%", ["UI_Cost2"] = "стоимость перелета | Расстояние {0}км | Скидка {1}%", ["UI_Call"] = "Вызов такси будет доступен через {0}ч.{1}м.{2}c.", ["UI_NoCall"] = "В данный момент нет свободных такси, попробуйте позже.", ["UI_Call2"] = "Вызвать", ["UI_Pay"] = "Оплатить", ["UI_Close"] = "Закрыть", ["UI_Refuse"] = "Отказаться", ["UI_Free"] = "Бесплатно"
            }
            , this, "ru");
        }
        string GetMsg(string key, BasePlayer player = null) => lang.GetMessage(key, this, player?.UserIDString);
        string GetMsg(string key) => lang.GetMessage(key, this);
#endregion
#region [Func]
        private void SpawnHelicopters() {
            var monument = TerrainMeta.Path.Monuments.Where(m => m.name.Contains(config.taxi.monument)).FirstOrDefault();
            if(monument == null) {
                PrintError($"Monument {config.taxi.monument} not found!");
                return;
            }
            List<Vector3> Spawns = new List<Vector3>();
            if (config.taxi.monument == "bandit_town") Spawns = SpawnsBandit;
            else Spawns = SpawnsComp;
            int i = 0;
            foreach (var spawn in Spawns) {
                if (i >= config.taxi.copterCount) return;
                var copter = GameManager.server.CreateEntity("assets/content/vehicles/scrap heli carrier/scraptransporthelicopter.prefab", monument.transform.position + monument.transform.rotation * spawn) as ScrapTransportHelicopter;
                copter.enableSaving = false;
                copter.Spawn();
                BasePlayer bot = GameManager.server.CreateEntity("assets/prefabs/player/player.prefab", copter.transform.position + new Vector3(-5f, 5f, 0f)).ToPlayer();
                bot.enableSaving = false;
                bot.Spawn();
                bot.displayName = config.taxi.name;
                foreach (var cloth in config.taxi.clothes) {
                    var item = ItemManager.CreateByName(cloth.Key, 1, cloth.Value);
                    item.MoveToContainer(bot.inventory.containerWear);
                }
                BaseMountable seat;
                bot.MountObject(seat = copter.GetIdealMountPoint(bot.eyes.position, bot.transform.position, bot));
                seat.AttemptMount(bot);
                var AI = copter.gameObject.AddComponent<AIcopter>();
                AI.SetCopterWaitOrderPos(monument.transform.position + monument.transform.rotation * spawn);
                AI.SetTaxiDriver(bot);
                Copters.Add(copter);
                i++;
            }
        }
        private bool IsPlayerOnHeli(BasePlayer player) {
            if (player.isMounted) {
                var heli = player.GetMountedVehicle() as ScrapTransportHelicopter;
                if (heli == null) return false;
                if (Copters.Contains(heli)) return true;
            }
            var ParentHeli = player.GetComponentInParent<ScrapTransportHelicopter>();
            if (ParentHeli != null) if (Copters.Contains(ParentHeli)) return true;
            return false;
        }
        private bool IsPlayerDriver(BasePlayer player) {
            if (player.isMounted) {
                var heli = player.GetMountedVehicle() as ScrapTransportHelicopter;
                if (heli == null) return false;
                if (Copters.Contains(heli)) {
                    var AI = heli.GetComponent<AIcopter>();
                    if (AI == null) return false;
                    if (AI.IsTaxiDriver(player)) return true;
                }
            }
            return false;
        }
        private bool ValidPosition(Vector3 randomPos, BasePlayer player = null) {
            if (WaterLevel.Test(randomPos + new Vector3(0, 1.3f, 0))) return true;
            var colliders = new List<Collider>();
            Vis.Colliders(randomPos, 8f, colliders);
            if (colliders.Where(col => col.name.ToLower().Contains("prevent") && col.name.ToLower().Contains("building")).Count() > 0) return true;
            var entities = new List<BaseEntity>();
            Vis.Entities(randomPos, 8f, entities);
            if (entities.Where(ent => ent is BaseVehicle || ent is CargoShip || ent is BaseHelicopter || ent is BradleyAPC || ent is BuildingBlock).Count() > 0) return true;
            Vis.Entities(randomPos, 4f, entities);
            if (entities.Where(ent => ent.PrefabName.Contains("resource")).Count() > 0) return true;
            var cupboards = new List<BuildingPrivlidge>();
            Vis.Entities(randomPos, 30f, cupboards);
            if (player == null) {
                if (cupboards.Count > 0) return false;
            }
            else {
                if (cupboards.Count <= 0) return true;
                foreach (var cup in cupboards) if (cup.IsAuthed(player)) return true;
                return false;
            }
            return true;
        }
        private bool IsAlreadyClient(BasePlayer player, AIcopter c) {
            foreach (var copter in Copters) {
                var AI = copter.GetComponent<AIcopter>();
                if (AI == null) continue;
                if (AI.GetTaxiClient() == player) {
                    if (AI == c) return false;
                    else return true;
                }
            }
            return false;
        }
        private bool IsAlreadyClient(BasePlayer player) {
            foreach (var copter in Copters) {
                var AI = copter.GetComponent<AIcopter>();
                if (AI == null) continue;
                if (AI.GetTaxiClient() == player) return true;
            }
            return false;
        }
        private int GetCost(float distance) => Convert.ToInt32(Math.Round(distance / 1000 * config.price.Cost));
        private bool HasPlayerItems(BasePlayer player, string shortname, int amount, ulong skinid = 0) {
            var playerHas = 0;
            foreach(var item in player.inventory.containerMain.itemList) {
                if (item.info.shortname == shortname && item.skin == skinid) playerHas += item.amount;
                if (playerHas >= amount) return true;
            }
            foreach (var item in player.inventory.containerBelt.itemList) {
                if (item.info.shortname == shortname && item.skin == skinid) playerHas += item.amount;
                if (playerHas >= amount) return true;
            }
            return false;
        }
        private void RemovePlayerItems(BasePlayer player, string shortname, int amount, ulong skinid = 0) {
            int count = amount;
            for (int i = 0; i < 24; i++) {
                var item = player.inventory.containerMain.GetSlot(i);
                if (item == null) continue;
                if (item.info.shortname == shortname && item.skin == skinid) {
                    if (item.amount > count) {
                        item.UseItem(count);
                        count = 0;
                    }
                    else if (item.amount < count) {
                        count -= item.amount;
                        item.UseItem(item.amount);
                    }
                    else {
                        item.UseItem(item.amount);
                        count = 0;
                    }
                    if (count == 0) return;
                }
            }
            for (int i = 0; i < 6; i++) {
                var item = player.inventory.containerBelt.GetSlot(i);
                if (item == null) continue;
                if (item.info.shortname == shortname && item.skin == skinid) {
                    if (item.amount > count) {
                        item.UseItem(count);
                        count = 0;
                    }
                    else if (item.amount < count) {
                        count -= item.amount;
                        item.UseItem(item.amount);
                    }
                    else {
                        item.UseItem(item.amount);
                        count = 0;
                    }
                    if (count == 0) return;
                }
            }
        }
        private string PayTaxi(BasePlayer player, int amount) {
            if (amount <= 0) return "paid";
            switch(config.price.type) {
                case "Economics" : return (bool)Economics?.Call("Withdraw", player.userID, Convert.ToDouble(amount)) ? "paid" : GetMsg("Nofunds", player);
                case "IQEconomic" : if ((bool)IQEconomic.Call("API_IS_REMOVED_BALANCE", player.userID, amount) == false) return GetMsg("Nofunds", player);
                IQEconomic.Call("API_REMOVE_BALANCE", player.userID, amount);
                return "paid";
                case "ServerRewards" : return ServerRewards?.Call("TakePoints", player.userID, amount) == null ? GetMsg("Nofunds", player) : "paid";
                case "Item" : if (!HasPlayerItems(player, config.price.shortname, amount)) return GetMsg("Nofunds", player);
                RemovePlayerItems(player, config.price.shortname, amount);
                return "paid";
                case "CustomItem" : if (!HasPlayerItems(player, config.price.shortname, amount, config.price.skinID)) return GetMsg("Nofunds", player);
                RemovePlayerItems(player, config.price.shortname, amount, config.price.skinID);
                return "paid";
            }
            return "Ошибка #100, сообщите администратору";
        }
        private int GetPlayerDiscount(BasePlayer player) {
            var discount = 0;
            foreach(var dis in config.taxi.discount.OrderByDescending(d => d.Value)) {
                if(permission.UserHasPermission(player.UserIDString, dis.Key)) {
                    discount = dis.Value;
                    break;
                }
            }
            return discount;
        }
        private void DisMountAllPlayers(Vector3 checkPos) {
            var players = new List<BasePlayer>();
            Vis.Entities(checkPos, 8f, players);
            float r = 0f;
            foreach(var player in players) {
                if (!player.IsConnected || !player.IsAlive()) continue;
                if(IsPlayerOnHeli(player)) {
                    if (player.isMounted) {
                        player.GetMounted().DismountPlayer(player);
                    }
                    player.Teleport(checkPos + new Vector3(-3f, 3f, r));
                    r += 1f;
                }
            }
        }
#endregion
#region [Oxide]
        private void OnServerInitialized() {
            SpawnHelicopters();
            permission.RegisterPermission(config.taxi.permmission, this);
            foreach (var perm in config.taxi.discount) permission.RegisterPermission(perm.Key, this);
            ImageLibrary?.Call("AddImage", config.ui.photoUrl, "taxiPhoto");
            if (config.price.type != "Item") ImageLibrary?.Call("AddImage", config.price.url, config.price.type + "_" + config.price.skinID);
        }
        private void Init() {
            plugin = this;
        }
        private void Unload() {
            plugin = null;
            foreach (var copter in Copters) {
                if (copter != null) {
                    var AI = copter.gameObject.GetComponent<AIcopter>();
                    AI.KillTaxiDriver();
                    UnityEngine.Object.Destroy(AI);
                    copter.Kill();
                }
            }
        }
        private object OnSamSiteTarget(SamSite entity, BaseCombatEntity target) {
            if (entity == null || target == null) return null;
            var heli = target as ScrapTransportHelicopter;
            if (!heli) return null;
            if (!Copters.Contains(heli)) return null;
            return false;
        }
        private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
            if (entity == null || info == null) return null;
            if (entity as ScrapTransportHelicopter) {
                if (Copters.Contains(entity as ScrapTransportHelicopter)) return false;
                return null;
            }
            var attacker = info?.InitiatorPlayer;
            var victim = entity?.ToPlayer();
            if (victim == null) return null;
            if (attacker == null) {
                if (IsPlayerOnHeli(victim)) return false;
                return null;
            }
            if (IsPlayerOnHeli(attacker) || IsPlayerOnHeli(victim)) return false;
            return null;
        }
        private object CanMountEntity(BasePlayer player, BaseMountable entity) {
            if (entity == null || player == null) return null;
            var copter = entity.VehicleParent() as ScrapTransportHelicopter;
            if (copter == null) return null;
            if (!Copters.Contains(copter)) return null;
            var AI = copter.GetComponent<AIcopter>();
            if (AI == null) return null;
            if (IsAlreadyClient(player, AI)) {
                CreatePayCopterTaxiUI(player, "", 0, GetMsg("AlreadyCall", player));
                return false;
            }
            if (AI.IsBusy()) return null;
            var client = AI.GetTaxiClient();
            if (client == null) {
                AI.SetStateWaitMarker();
                AI.SetNewClient(player);
                player.SendConsoleCommand("chat.add", new object[] {
                    0, config.taxi.chatIcon, String.Format(GetMsg("Say1", player), config.taxi.name)
                }
                );
                return null;
            }
            if (player.userID == AI.GetTaxiClient().userID && AI.CanSetMarker()) player.SendConsoleCommand("chat.add", new object[] {
                0, config.taxi.chatIcon, String.Format(GetMsg("Say1", player), config.taxi.name)
            }
            );
            return null;
        }
        private void OnEntityDismounted(BaseMountable entity, BasePlayer player) {
            var copter = entity.VehicleParent() as ScrapTransportHelicopter;
            if (copter == null) return;
            if (!Copters.Contains(copter)) return;
            var AI = copter.GetComponent<AIcopter>();
            if (AI == null) return;
            if (Vector3.Distance(copter.transform.position, AI.GetCopterWaitOrderPos()) < 10f) {
                AI.SetStateWaitOrder();
                AI.SetNewClient(null);
                player.SendConsoleCommand("chat.add", new object[] {
                    0, config.taxi.chatIcon, String.Format(GetMsg("Say2", player), config.taxi.name)
                }
                );
                return;
            }
        }
        private void OnMapMarkerAdded(BasePlayer player, MapNote note) {
            if (!player.isMounted) return;
            var copter = player.GetMountedVehicle() as ScrapTransportHelicopter;
            if (copter == null) return;
            if (!Copters.Contains(copter)) return;
            var AI = copter.GetComponent<AIcopter>();
            if (AI == null) return;
            if (!AI.CanSetMarker()) return;
            var client = AI.GetTaxiClient();
            if (client == null) return;
            if (client.userID != player.userID) return;
            RaycastHit hitInfo;
            Physics.Raycast(note.worldPosition + new Vector3(0f, 120f, 0f), Vector3.down, out hitInfo, 500f, Layers.Solid);
            if (!ValidPosition(hitInfo.point, player)) {
                CreatePayCopterTaxiUI(player, "", 0, GetMsg("Cant", player));
                return;
            }
            if (Vector3.Distance(copter.transform.position, hitInfo.point) < 50f) {
                CreatePayCopterTaxiUI(player, "", 0, GetMsg("Near", player));
                return;
            }
            var metre = Vector3.Distance(hitInfo.point, AI.transform.position - new Vector3(0, AI.GetFlyHeight(), 0));
            var cost = Convert.ToInt32(Math.Round(metre / 1000 * config.price.Cost));
            var disc = GetPlayerDiscount(player);
            if (disc < 100) cost = cost - (cost / 100 * GetPlayerDiscount(player));
            else cost = 0;
            CreatePayCopterTaxiUI(player, (metre / 1000).ToString("0.00"), cost);
            AI.SetMarkerPos(hitInfo.point);
        }
        private object CanBuild(Planner plan, Construction prefab) {
            if (plan == null) return null;
            var player = plan?.GetOwnerPlayer();
            if (player == null) return null;
            foreach(var copter in Copters) {
                //Add
                if (copter == null) continue;
                var AI = copter.GetComponent<AIcopter>();
                if (AI == null) continue;
                if (!AI.IsBusy()) continue;
                if (AI.GoToPlayer()) {
                    if (Vector3.Distance(player.transform.position, AI.GetCopterPlayerPos()) < 15f) {
                        player.ChatMessage(GetMsg("NoBuild1", player));
                        return false;
                    }
                }
                else if (AI.GoToMarker()) {
                    if (Vector3.Distance(player.transform.position, AI.GetCopterMarkerPos()) < 15f) {
                        player.ChatMessage(GetMsg("NoBuild1", player));
                        return false;
                    }
                }
                else if(AI.WaitMarker()) {
                    if (Vector3.Distance(player.transform.position, AI.transform.position) < 15f) {
                        player.ChatMessage(GetMsg("NoBuild2", player));
                        return false;
                    }
                }
            }
            return null;
        }
        private object OnTurretTarget(AutoTurret turret, BaseCombatEntity entity) {
            if (turret == null || entity == null) return null;
            if (entity.ToPlayer() == null) return null;
            if (IsPlayerDriver(entity.ToPlayer())) return false;
            return null;
        }
#endregion
#region [Command]
        [ChatCommand("taxi")]
        private void cmd_CallTaxi(BasePlayer player, string c, string[] a) {
            if (!permission.UserHasPermission(player.UserIDString, config.taxi.permmission)) {
                player.ChatMessage(GetMsg("NoPerm", player));
                return;
            }
            CreateCallCopterTaxiUI(player);
        }
        [ChatCommand("tt")]
        void casdas(BasePlayer player, string c, string[] a) {
            var entities = new List<BaseEntity>();
            Vis.Entities(player.transform.position, 1f, entities);
            foreach (var ent in entities) player.ChatMessage(ent.PrefabName);
        }
#endregion
#region [AI]
        public class AIcopter : MonoBehaviour {
            private ScrapTransportHelicopter copter;
            private EntityFuelSystem fuelSystem;
            private VehicleEngineController<MiniCopter> engineController;
            private BasePlayer client;
            private BasePlayer driver;
            private Vector3 WaitOrderPos;
            private Vector3 PlayerPos;
            private Vector3 MarkerPos;
            private Timer speedTimer;
            private float speed;
            private bool Up;
            private bool Down;
            private bool Rotate;
            private bool Stop;
            private bool Engine;
            private bool LowSpeed;
            private bool SearhedLet;
            private bool Let;
            private FlyStates State;
            private float rotationSpeed;
            private float FlyHeight;
            private float WaitSecondsMarker;
            private int time;
            private int wait;
            private RaycastHit hitInfo;
            private RaycastHit RayLine;
            private Vector3 move;
            private int HeightTime;
            private int testtime = 0;
            private enum FlyStates {
                FlyToPlayer = 1, FlyToStart = 2, FlyToMarker = 3, WaitOrder = 4, WaitMarker = 5
            }
            private void Awake() {
                copter = gameObject.GetComponent<ScrapTransportHelicopter>();
                fuelSystem = copter.GetFuelSystem();
                engineController = copter.engineController;
            }
            private void Start() {
                Up = false;
                Down = false;
                Rotate = false;
                Stop = true;
                Engine = false;
                LowSpeed = true;
                SearhedLet = false;
                State = FlyStates.WaitOrder;
                speed = plugin.config.taxi.copterSpeed;
                rotationSpeed = 0.5f;
                FlyHeight = plugin.config.taxi.copterFly;
                if (FlyHeight < 80) {
                    FlyHeight = 80;
                    plugin.PrintError("Taxi FlyHeight cant be lower 80");
                }
                WaitSecondsMarker = plugin.config.taxi.copterWaitPay;
            }
            private void FixedUpdate() {
                if (Engine) {
                    fuelSystem.TryUseFuel(0f, copter.fuelPerSec);
                    engineController.FinishStartingEngine();
                }
                if (Up || Down) speed = 0.5f;
                switch (State) {
#region [FlyToPlayer]
                    case FlyStates.FlyToPlayer : if (Stop) return;
                    if (Up == true) {
                        MoveObj(new Vector3(WaitOrderPos.x, FlyHeight, WaitOrderPos.z));
                        if (Rotate) RotateObj(new Vector3(PlayerPos.x, transform.position.y, PlayerPos.z));
                        if (Vector3.Distance(transform.position, new Vector3(WaitOrderPos.x, FlyHeight, WaitOrderPos.z)) < 5f) {
                            Up = false;
                            Rotate = false;
                            LowSpeed = true;
                            move = PlayerPos;
                            move.y = FlyHeight;
                            StartCoroutine(Hover(2f));
                            ChangeSpeed(1);
                        }
                        return;
                    }
                    if (Down == true) {
                        if (Vector3.Distance(transform.position, PlayerPos) < 15f) speed = 0.3f;
                        if (Vector3.Distance(transform.position, PlayerPos) < 10f) speed = 0.2f;
                        MoveObj(PlayerPos);
                        if (Vector3.Distance(transform.position, PlayerPos) < 1.5f) {
                            Stop = true;
                            Engine = false;
                            State = FlyStates.WaitMarker;
                            wait = Facepunch.Math.Epoch.Current;
                            StartCoroutine(WaitMarker(WaitSecondsMarker));
                            Down = false;
                            client.SendConsoleCommand("chat.add", new object[] {
                                0, plugin.config.taxi.chatIcon, String.Format(plugin.GetMsg("Say3", client), plugin.config.taxi.name)
                            }
                            );
                        }
                        return;
                    }
                    if (client != null) {
                        if (Facepunch.Math.Epoch.Current - time >= 2) {
                            SetPlayerFlag(client, BasePlayer.PlayerFlags.IsAdmin, true);
                            client.SendConsoleCommand("ddraw.text", 2.01f, Color.white, PlayerPos + new Vector3(0, 2f, 0), String.Format(plugin.GetMsg("Distance", client), (Vector3.Distance(transform.position - new Vector3(0, FlyHeight, 0), PlayerPos) / 1000).ToString("0.00")));
                            SetPlayerFlag(client, BasePlayer.PlayerFlags.IsAdmin, false);
                            time = Facepunch.Math.Epoch.Current;
                        }
                    }
                    if (Vector3.Distance(transform.position, PlayerPos + new Vector3(0, FlyHeight, 0)) < 100f) if (LowSpeed) ChangeSpeed(2);
                    if (Vector3.Distance(transform.position, move) < 10f) {
                        StartCoroutine(Hover(2f));
                        Down = true;
                        MoveObj(move);
                    }
                    else MoveObj(move);
                    break;
#endregion
#region [FlyToStart]
                    case FlyStates.FlyToStart : if (Stop) return;
                    if (Up == true) {
                        MoveObj(PlayerPos + new Vector3(0f, FlyHeight, 0f));
                        if (Rotate) RotateObj(new Vector3(WaitOrderPos.x, transform.position.y, WaitOrderPos.z));
                        if (Vector3.Distance(transform.position, PlayerPos + new Vector3(0f, FlyHeight, 0f)) < 5f) {
                            Up = false;
                            Rotate = false;
                            LowSpeed = true;
                            move = WaitOrderPos;
                            move.y = FlyHeight;
                            StartCoroutine(Hover(2f));
                            ChangeSpeed(1);
                        }
                        return;
                    }
                    if (Down == true) {
                        if (Vector3.Distance(transform.position, WaitOrderPos) < 15f) speed = 0.3f;
                        if (Vector3.Distance(transform.position, WaitOrderPos) < 10f) speed = 0.2f;
                        MoveObj(WaitOrderPos);
                        if (Vector3.Distance(transform.position, WaitOrderPos) < 0.8f) {
                            Stop = true;
                            Engine = false;
                            State = FlyStates.WaitOrder;
                            client = null;
                            MarkerPos = Vector3.zero;
                            Down = false;
                        }
                        return;
                    }
                    if (Vector3.Distance(transform.position, WaitOrderPos + new Vector3(0, FlyHeight, 0)) < 100f) if (LowSpeed) ChangeSpeed(2);
                    if (Vector3.Distance(transform.position, move) < 10f) {
                        StartCoroutine(Hover(2f));
                        Down = true;
                        MoveObj(move);
                    }
                    else MoveObj(move);
                    break;
#endregion
#region [FlyToMarker]
                    case FlyStates.FlyToMarker : if (Stop) return;
                    if (Up == true) {
                        MoveObj(PlayerPos + new Vector3(0f, FlyHeight, 0f));
                        if (Rotate) RotateObj(new Vector3(MarkerPos.x, transform.position.y, MarkerPos.z));
                        if (Vector3.Distance(transform.position, PlayerPos + new Vector3(0f, FlyHeight, 0f)) < 5f) {
                            Up = false;
                            Rotate = false;
                            LowSpeed = true;
                            move = MarkerPos;
                            move.y = FlyHeight;
                            StartCoroutine(Hover(2f));
                            ChangeSpeed(1);
                        }
                        return;
                    }
                    if (Down == true) {
                        if (Vector3.Distance(transform.position, MarkerPos) < 15f) speed = 0.3f;
                        if (Vector3.Distance(transform.position, MarkerPos) < 10f) speed = 0.2f;
                        MoveObj(MarkerPos);
                        if (Vector3.Distance(transform.position, MarkerPos) < 1.5f) {
                            StartCoroutine(WaitOut(15f));
                            Stop = true;
                            Engine = false;
                            Down = false;
                        }
                        return;
                    }
                    if (Facepunch.Math.Epoch.Current - time >= 2) {
                        if (client != null) {
                            SetPlayerFlag(client, BasePlayer.PlayerFlags.IsAdmin, true);
                            client.SendConsoleCommand("ddraw.text", 2.01f, Color.white, MarkerPos + new Vector3(0, 3f, 0), String.Format(plugin.GetMsg("Distance", client), (Vector3.Distance(MarkerPos, transform.position - new Vector3(0, FlyHeight, 0)) / 1000).ToString("0.00")));
                            SetPlayerFlag(client, BasePlayer.PlayerFlags.IsAdmin, false);
                            time = Facepunch.Math.Epoch.Current;
                        }
                    }
                    if (Vector3.Distance(transform.position, MarkerPos + new Vector3(0, FlyHeight, 0)) < 100f) if (LowSpeed) ChangeSpeed(2);
                    if (Vector3.Distance(transform.position, move) < 10f) {
                        StartCoroutine(Hover(2f));
                        Down = true;
                        MoveObj(move);
                    }
                    else MoveObj(move);
                    break;
#endregion
#region [WaitMarker]
                    case FlyStates.WaitMarker : if (client != null) {
                        if (Vector3.Distance(transform.position, WaitOrderPos) > 10f) {
                            if (Facepunch.Math.Epoch.Current - time >= 2) {
                                var wtime = TimeSpan.FromSeconds(wait + plugin.config.taxi.copterWaitPay - Facepunch.Math.Epoch.Current);
                                SetPlayerFlag(client, BasePlayer.PlayerFlags.IsAdmin, true);
                                client.SendConsoleCommand("ddraw.text", 2.01f, Color.white, transform.position + new Vector3(0, 4f, 0), String.Format(plugin.GetMsg("Marker", client), wtime.Minutes, wtime.Seconds));
                                SetPlayerFlag(client, BasePlayer.PlayerFlags.IsAdmin, false);
                                time = Facepunch.Math.Epoch.Current;
                            }
                        }
                    }
                    break;
#endregion
                }
            }
            private void MoveObj(Vector3 move) {
                if (transform.position.y < FlyHeight - 5f && SearhedLet && !Let) {
                    transform.position = Vector3.MoveTowards(transform.position, new Vector3(transform.position.x, FlyHeight, transform.position.z), 1f);
                }
                else {
                    transform.position = Vector3.MoveTowards(transform.position, move, speed);
                }
            }
            private void RotateObj(Vector3 look) {
                Quaternion targetRotation = Quaternion.LookRotation(look - transform.position);
                transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
            }
            private void ChangeSpeed(int action) {
                speedTimer?.Destroy();
                if (action == 1) {
                    SearhedLet = true;
                    InvokeRepeating("CheckLet", 0.5f, 0.5f);
                    speedTimer = plugin.timer.Every(1f, () => {
                        if (speed >= plugin.config.taxi.copterSpeed + plugin.config.taxi.copterSpeedUp) {
                            speed = plugin.config.taxi.copterSpeed;
                            speedTimer.Destroy();
                            return;
                        }
                        speed += plugin.config.taxi.copterSpeedUp;
                    }
                    );
                }
                else if (action == 2) {
                    LowSpeed = false;
                    SearhedLet = false;
                    speedTimer = plugin.timer.Every(2f, () => {
                        if (speed <= 1f) {
                            speed = 1f;
                            speedTimer.Destroy();
                            return;
                        }
                        speed -= plugin.config.taxi.copterSpeedLow;
                    }
                    );
                }
            }
            private void CheckLet() {
                if (!SearhedLet) {
                    CancelInvoke("CheckLet");
                    return;
                }
                Vector3 pos = new Vector3(transform.position.x, FlyHeight - 5f, transform.position.z);
                Vector3 direct = pos + transform.rotation * new Vector3(0, 0, 100f);
                if (Physics.Linecast(pos, direct, out RayLine, Layers.Solid)) {
                    if (RayLine.distance < 10f) return;
                    Let = true;
                    FlyHeight += 15;
                    move.y = FlyHeight;
                }
                else {
                    Let = false;
                }
            }
#region [IEnumerator]
            IEnumerator GoToPoint(FlyStates state) {
                Engine = true;
                FlyHeight = plugin.config.taxi.copterFly;
                yield return new WaitForSeconds(7f);
                Stop = false;
                Rotate = true;
                Up = true;
                if (state == FlyStates.FlyToStart || state == FlyStates.FlyToMarker) PlayerPos = transform.position;
                State = state;
                yield return new WaitForSeconds(1f);
                if (state == FlyStates.FlyToStart) plugin.DisMountAllPlayers(transform.position);
                yield return null;
            }
            IEnumerator WaitMarker(float wait) {
                yield return new WaitForSeconds(wait);
                if (State == FlyStates.WaitMarker) {
                    PlayerPos = transform.position;
                    State = FlyStates.FlyToStart;
                    StartCoroutine(GoToPoint(FlyStates.FlyToStart));
                }
                yield return null;
            }
            IEnumerator WaitOut(float wait) {
                yield return new WaitForSeconds(wait);
                PlayerPos = transform.position;
                MarkerPos = Vector3.zero;
                client = null;
                StartCoroutine(GoToPoint(FlyStates.FlyToStart));
                yield return null;
            }
            IEnumerator Hover(float time) {
                Stop = true;
                yield return new WaitForSeconds(time);
                Stop = false;
                yield return null;
            }
#endregion
#region [Func]
            public void SetCopterWaitOrderPos(Vector3 pos) => WaitOrderPos = pos;
            public Vector3 GetCopterWaitOrderPos() => WaitOrderPos;
            //Add
            public Vector3 GetCopterPlayerPos() {
                if (PlayerPos == null) return Vector3.zero;
                return PlayerPos;
            }
            public Vector3 GetCopterMarkerPos() => MarkerPos;
            public void SetTaxiDriver(BasePlayer bot) => driver = bot;
            public bool IsTaxiDriver(BasePlayer bot) => driver == bot;
            public BasePlayer GetTaxiClient() => client;
            public void KillTaxiDriver() => driver.Kill();
            public void SetStateWaitMarker() => State = FlyStates.WaitMarker;
            public void SetStateWaitOrder() => State = FlyStates.WaitOrder;
            public void SetNewClient(BasePlayer player) => client = player;
            public float GetFlyHeight() => FlyHeight;
            public void SetMarkerPos(Vector3 pos) => MarkerPos = pos;
            public bool IsBusy() {
                if (State == FlyStates.WaitOrder) return false;
                return true;
            }
            public bool CanSetMarker() {
                if (State == FlyStates.WaitMarker) return true;
                return false;
            }
            public bool GoToPlayer() {
                if (State == FlyStates.FlyToPlayer) return true;
                return false;
            }
            public bool GoToMarker() {
                if (State == FlyStates.FlyToMarker) return true;
                return false;
            }
            public bool WaitMarker() {
                if (State == FlyStates.WaitMarker) return true;
                return false;
            }
            public void SetCopterClient(BasePlayer player) {
                client = player;
                PlayerPos = player.transform.position;
                State = FlyStates.FlyToPlayer;
                StartCoroutine(GoToPoint(FlyStates.FlyToPlayer));
            }
            public void GoMarkerPosition() {
                PlayerPos = transform.position;
                StartCoroutine(GoToPoint(FlyStates.FlyToMarker));
                State = FlyStates.FlyToMarker;
            }
            void SetPlayerFlag(BasePlayer player, BasePlayer.PlayerFlags f, bool b) {
                if (plugin.permission.UserHasGroup(player.UserIDString, "admin")) return;
                if (b) {
                    if (player.HasPlayerFlag(f)) return;
                    player.playerFlags |= f;
                }
                else {
                    if (!player.HasPlayerFlag(f)) return;
                    player.playerFlags &= ~f;
                }
                player.SendNetworkUpdateImmediate(false);
            }
#endregion
        }
#endregion
#region [UI]
        private void CreateCallCopterTaxiUI(BasePlayer player) {
            CuiElementContainer container = new CuiElementContainer();
            container.Add(new CuiElement {
                Parent
// ... [Code preview truncated due to length. Full source in attached file] ...

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