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

FREE WaterBikes : 1.4.0 1.4.0

Нет прав для скачивания
C#:
using Facepunch;
using Network;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core.Plugins;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;


namespace Oxide.Plugins
{
    [Info("WaterBikes", "senyaa", "1.4.0")]
    [Description("Turns snowmobiles into waterbikes")]
    class WaterBikes : RustPlugin
    {
        #region Optional Dependencies
        [PluginReference]
        Plugin ServerRewards, Economics;

        static bool? TakePoints(ulong playerID, int amount) => Instance.ServerRewards?.Call("TakePoints", playerID, amount) as bool?;
        static int? CheckPoints(ulong ID) => Instance.ServerRewards?.Call("CheckPoints", ID) as int?;

        static bool? Economics_Withdraw(string playerId, double amount) => Instance.Economics?.Call("Withdraw", playerId, amount) as bool?;
        #endregion

        #region Dependency Boilerplate
        public static bool CheckDependency(string plugin_name)
        {
            var fields = Instance.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
            foreach (var field in fields)
            {
                if (field.FieldType != typeof(Plugin))
                {
                    continue;
                }

                if (field.Name.ToLower() != plugin_name.ToLower())
                {
                    continue;
                }

                if (field.GetValue(Instance) == null)
                {
                    continue;
                }

                return true;
            }
            return false;
        }

        public static bool CheckDependencyAndPrintWarning(string plugin_name, BasePlayer player = null)
        {
            if (!CheckDependency(plugin_name))
            {
                Instance.PrintError($"{plugin_name} is not installed, but it is used in the config.Execution aborted!");

                if (player != null)
                {
                    Instance.PrintToChat(player, $"<color=red>{plugin_name} is not installed, but it is used in the config.Execution aborted!</color>");
                }

                return false;
            }
            return true;
        }
        #endregion

        #region Constants
        const int HAMMER_ITEMID = 200773292;

        const int BEACHSIDE_TOPOLOGY = 16;
        const int BEACH_TOPOLOGY = 8;
        const int OCEANSIDE_TOPOLOGY = 256;

        const string SPAWN_PERMISSION = "waterbikes.spawn";
        const string FREE_PERMISSION = "waterbikes.free";
        const string DESPAWN_PERMISSION = "waterbikes.despawn";
        const string ADMIN_PERMISSION = "waterbikes.admin";
        const string BUY_PERMISSION = "waterbikes.buy";
        #endregion

        #region Fields
        public static WaterBikes Instance;
        private static Dictionary<BaseNetworkable, WaterBikeComponent> waterbikes;
        private Dictionary<BasePlayer, Snowmobile> playerWaterbikes;
        private List<BasePlayer> cooldownList;
        private ItemDefinition priceDef;
        private Vector3 lastKilledSnowmobilePos; // workaround to get water bikes work properly with spray can reskinning
        #endregion

        #region Configuration
        private class Configuration : SerializableConfiguration
        {
            [JsonProperty("(1.1) Waterbike price (set value to 0 to make it free, use ServerRewards or Economics as a shortname to use RP points or Economics balance respectively)")]
            public Price Price = new Price
            {
                ShortName = "scrap",
                Amount = 75,
                SkinID = 0
            };

            [JsonProperty("(1.2) Spawn cooldown (in seconds)")]
            public int Cooldown = 120;

            [JsonProperty("(1.3) Allow only 1 water bike per player")]
            public bool AllowOnlyOneWaterBikePerPlayer = false;

            [JsonProperty("(1.4) Allow spawning water bikes only on beaches")]
            public bool spawnOnlyOnBeaches = false;

            [JsonProperty("(1.5) Amount of water bikes /buywaterbike command gives")]
            public int AmountPerBuy = 1;

            [JsonProperty("(1.6) Starting fuel")]
            public int startingFuel = 0;
            [JsonProperty("(2.2) How much HP is reduced when the water bike is picked up (0-100)")]
            public float HP_Reduction = 25f;

            [JsonProperty("(2.3) Water bike item name")]
            public string ItemName = "Water Bike";

            [JsonProperty("(2.4) Water bike item skin ID")]
            public ulong ItemSkinID = 2935987835;

            [JsonProperty("(2.5) Water bike item ID")]
            public int ItemID = 794443127;

            [JsonProperty("(3.1) Make all snowmobiles waterbikes")]
            public bool Make_All_Snowmobiles_Waterbikes = true;

            [JsonProperty("(3.2) Allow waterbikes to drive on land")]
            public bool Allow_To_Move_On_Land = true;

            [JsonProperty("(4.1) Enable 'boost' button (Left Shift)")]
            public bool enableBoostButton = false;

            [JsonProperty("(4.2) 'Boost' button thrust")]
            public float boostButtonThrust = 10000f;

            [JsonProperty("(4.3) 'Boost' duration (seconds)")]
            public float boostDuration = 5f;

            [JsonProperty("(4.4) 'Boost' cooldown (seconds)")]
            public float boostCooldown = 30f;

            [JsonProperty("(5.1) Engine thrust")]
            public int engineThrust = 5000;

            [JsonProperty("(5.2) Engine thrust on land")]
            public int engineThrustOnLand = 49;

            [JsonProperty("(5.3) Move slowly on grass or roads")]
            public bool slowlyOnGrass = true;

            [JsonProperty("(5.4) Steering scale")]
            public float steeringScale = 0.05f;

            [JsonProperty("(5.5) Automatically flip water bikes")]
            public bool autoFlip = false;

            [JsonProperty("(5.6) Off axis drag")]
            public float offAxisDrag = 0.35f;

            [JsonProperty("(5.7) Buoyancy force")]
            public float buoyancyForce = 730f;

            [JsonProperty("(6.1) Waterbike prefab")]
            public string WaterbikePrefab = "assets/content/vehicles/snowmobiles/tomahasnowmobile.prefab";

            [JsonProperty("(6.2) Thrust point position")]
            public Vector3 ThrustPoint = new Vector3(-0.001150894f, 0.055f, -1.125f);

            [JsonProperty("(6.3) Buoyancy points")]
            public SerializedBuoyancyPoint[] BuoyancyPoints = new SerializedBuoyancyPoint[]
            {
                new SerializedBuoyancyPoint(new Vector3(-0.62f, 0.09f, -1.284f), 1.3f),
                new SerializedBuoyancyPoint(new Vector3(0.5f, 0.09f, -1.284f), 1.3f),
                new SerializedBuoyancyPoint(new Vector3(-0.68f, 0.09f, -0.028f), 1.3f),
                new SerializedBuoyancyPoint(new Vector3(0.54f, 0.09f, -0.028f), 1.3f),
                new SerializedBuoyancyPoint(new Vector3(-0.64f, 0.09f, 1.283f), 1.3f),
                new SerializedBuoyancyPoint(new Vector3(0.53f, 0.09f, 1.283f), 1.3f),
                new SerializedBuoyancyPoint(new Vector3(-0.05f, 0.148f, 3.015f), 1.3f),
                new SerializedBuoyancyPoint(new Vector3(-0.05f, 0.129f, 1.81f), 1.3f),
                new SerializedBuoyancyPoint(new Vector3(-0.05f, 0.529f, -0.828f), 1.3f)
            };
        }
        #endregion

        #region Configuration Boilerplate
        static Configuration config;

        private class SerializableConfiguration
        {

            [JsonProperty("(2.1) Allow picking up the water bike only in building privilege")]
            public bool Allow_Pickup_Only_In_Building_Privilege = false;
            public string ToJson() => JsonConvert.SerializeObject(this);

            public Dictionary<string, object> ToDictionary() => JsonHelper.Deserialize(ToJson()) as Dictionary<string, object>;
        }

        private static class JsonHelper
        {
            public static object Deserialize(string json) => ToObject(JToken.Parse(json));

            private static object ToObject(JToken token)
            {
                switch (token.Type)
                {
                    case JTokenType.Object:
                        return token.Children<JProperty>().ToDictionary(prop => prop.Name,
                                                  prop => ToObject(prop.Value));

                    case JTokenType.Array:
                        return token.Select(ToObject).ToList();

                    default:
                        return ((JValue)token).Value;
                }
            }
        }

        private bool ValidateConfig(Dictionary<string, object> currentWithDefaults, Dictionary<string, object> currentRaw)
        {
            var changed = false;
            var oldKeys = new List<string>();

            foreach (var key in currentRaw.Keys)
            {
                if (currentWithDefaults.Keys.Contains(key))
                {
                    continue;
                }

                changed = true;
                oldKeys.Add(key);
            }

            foreach (var key in oldKeys)
            {
                currentRaw.Remove(key);
            }

            foreach (var key in currentWithDefaults.Keys)
            {
                object currentRawValue;
                if (currentRaw.TryGetValue(key, out currentRawValue))
                {
                    var defaultDictValue = currentWithDefaults[key] as Dictionary<string, object>;
                    var currentDictValue = currentRawValue as Dictionary<string, object>;

                    if (defaultDictValue != null)
                    {
                        if (currentDictValue == null)
                        {
                            currentRaw[key] = currentWithDefaults[key];
                            changed = true;
                            continue;
                        }

                        if (ValidateConfig(defaultDictValue, currentDictValue))
                        {
                            changed = true;
                        }
                    }
                    continue;
                }

                currentRaw[key] = currentWithDefaults[key];
                changed = true;
            }


            return changed;
        }

        protected override void LoadDefaultConfig() => config = new Configuration();

        protected override void LoadConfig()
        {
            base.LoadConfig();

            try
            {
                config = Config.ReadObject<Configuration>();
                if (config == null)
                {
                    throw new JsonException();
                }

                var currentWithDefaults = config.ToDictionary();
                var currentRaw = Config.ToDictionary(x => x.Key, x => x.Value);

                if (ValidateConfig(currentWithDefaults, currentRaw))
                {
                    PrintWarning("Configuration appears to be outdated; updating and saving");
                    SaveConfig();
                }
            }
            catch
            {
                PrintWarning($"Configuration file {Name}.json is invalid; using defaults");
                LoadDefaultConfig();
            }
        }

        protected override void SaveConfig()
        {
            Puts($"Configuration changes saved to {Name}.json");
            Config.WriteObject(config, true);
        }
        #endregion

        #region Localization
        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["NoPermission"] = "You don't have permission to run this command",
                ["Spawned"] = "Spawned waterbike",
                ["NoWaterbike"] = "You aren't on a waterbike",
                ["Showing"] = "Showing buoyancy points...",
                ["NotEnough"] = "You don't have enough to buy a waterbike",
                ["Converted"] = "Snowmobile converted into waterbike",
                ["Cooldown"] = "You are on cooldown!",
                ["onlyBeach"] = "You can spawn water bikes only on beaches",
                ["onlyOne"] = "You can have only 1 water bike",
                ["removed"] = "Waterbike is removed",
                ["waterbikeDoesntExist"] = "You don't have a water bike",
                ["boostToast"] = "You can press LSHIFT to boost",
                ["lookat"] = "Look at a water bike",
                ["waterbikeGiven"] = "Water bike has been given to you"
            }, this, "en");

            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["NoPermission"] = "У вас нет прав для выполнения этой команды",
                ["Spawned"] = "Заспаунен гидроцикл",
                ["NoWaterbike"] = "Не на гидроцикле",
                ["Showing"] = "Показываются точки плавучести...",
                ["NotEnough"] = "У вас не хватает ресурсов для покупки гидроцикла",
                ["Converted"] = "Снегоход переделан в гидроцикл",
                ["Cooldown"] = "Вы не можете спаунить гидроциклы так быстро",
                ["onlyBeach"] = "Вы можете заспаунить гидроцикл только на пляже",
                ["onlyOne"] = "Только 1 гидроцикл на игрока",
                ["removed"] = "Гидроцикл удалён",
                ["waterbikeDoesntExist"] = "У вас нет гидроцикла",
                ["boostToast"] = "Вы можете нажать LSHIFT для ускорения",
                ["lookat"] = "Смотрите на гидроцикл",
                ["waterbikeGiven"] = "Вам был выдан гидроцикл"
            }, this, "ru");
        }
        #endregion

        #region Types
        public struct Price
        {
            public string ShortName;
            public int Amount;
            public ulong SkinID;

            public Price(string ShortName, int Amount, ulong SkinID)
            {
                this.ShortName = ShortName;
                this.Amount = Amount;
                this.SkinID = SkinID;
            }

            public bool TryPaying(BasePlayer player, string bypass_permission, string noPointsText, string noResourcesText)
            {
                var normalizedName = ShortName.ToLower();

                if ((normalizedName == "serverrewards" || normalizedName == "economics") && !CheckDependencyAndPrintWarning(normalizedName, player))
                {
                    return false;
                }


                if (!Instance.permission.UserHasPermission(player.UserIDString, bypass_permission) && Amount > 0)
                {
                    switch (normalizedName)
                    {
                        case "serverrewards":
                            var points = CheckPoints(player.userID);

                            if (points == null || points < Amount)
                            {
                                Instance.PrintToChat(player, noPointsText);
                                return false;
                            }

                            TakePoints(player.userID, Amount);
                            break;
                        case "economics":
                            if (Economics_Withdraw(player.UserIDString, Amount) == false)
                            {
                                Instance.PrintToChat(player, noPointsText);
                                return false;
                            }
                            break;
                        default:
                            var itemDef = ItemManager.FindItemDefinition(ShortName);

                            if (SkinID != 0)
                            {
                                var playerItems = Pool.GetList<Item>();
                                var itemsToCollect = Pool.GetList<Item>();

                                player.inventory.AllItemsNoAlloc(ref playerItems);

                                foreach (var item in playerItems)
                                {
                                    if (item.skin == SkinID && item.info.shortname == ShortName && item.amount > 0)
                                    {
                                        itemsToCollect.Add(item);
                                    }
                                }

                                if (itemsToCollect.Count < Amount)
                                {
                                    Instance.PrintToChat(player, string.Format(noResourcesText, itemDef.displayName.english.ToLower()));
                                    return false;
                                }

                                foreach (var item in itemsToCollect)
                                {
                                    item.RemoveFromContainer();
                                }

                                Pool.FreeList(ref itemsToCollect);
                                Pool.FreeList(ref playerItems);

                                break;
                            }

                            if (player.inventory.GetAmount(itemDef.itemid) < Amount)
                            {
                                Instance.PrintToChat(player, string.Format(noResourcesText, itemDef.displayName.english.ToLower()));
                                return false;
                            }

                            player.inventory.Take(null, itemDef.itemid, Amount);

                            break;
                    }
                }

                return true;
            }
        }

        private struct SerializedBuoyancyPoint
        {
            public Vector3 Position;
            public float Size;
            public SerializedBuoyancyPoint(Vector3 Position, float Size)
            {
                this.Position = Position;
                this.Size = Size;
            }
        }

        private class WaterBikeComponent : FacepunchBehaviour
        {
            private Snowmobile _snowmobile;
            private Buoyancy _buoyancy;
            private Rigidbody _rigidbody;

            public GameObject thrustPoint;
            private GameObject parentPoint;

            private float gasPedal;
            private float steering;

            private int framesSinceLastFlip;
            private int framesSinceLastInWater;

            private bool boosting;
            private bool boostCooldown;

            private Vector3 _waterLoggedPointLocalPosition;

            private int framesSinceLastControl;

            void Awake()
            {
                _snowmobile = GetComponent<Snowmobile>();
                _rigidbody = _snowmobile.gameObject.GetComponent<Rigidbody>();

                _snowmobile.engineKW = config.Allow_To_Move_On_Land ? config.engineThrustOnLand : -1;

                if (_snowmobile.waterloggedPoint != null && _snowmobile.waterloggedPoint.parent != null)
                {
                    _waterLoggedPointLocalPosition = _snowmobile.waterloggedPoint.localPosition;
                    _snowmobile.waterloggedPoint.SetParent(null);
                    _snowmobile.waterloggedPoint.position = new Vector3(0, 2000, 0);
                }

                thrustPoint = new GameObject("ThrustPoint");
                thrustPoint.transform.SetParent(_snowmobile.transform, false);
                thrustPoint.transform.localPosition = config.ThrustPoint;
                InitBuoyancy();
                _snowmobile.SetFlag(BaseEntity.Flags.Reserved10, true, true, true);
                waterbikes.Add(_snowmobile, this);

                _snowmobile.SendNetworkUpdateImmediate();
            }

            void OnDestroy()
            {
                Destroy(_buoyancy);
                Destroy(parentPoint);
                Destroy(thrustPoint);
                if (_snowmobile.IsDestroyed)
                {
                    return;
                }

                _snowmobile.waterloggedPoint.SetParent(_snowmobile.transform);
                _snowmobile.waterloggedPoint.transform.localPosition = _waterLoggedPointLocalPosition;
                _snowmobile.engineKW = 49;
                _snowmobile.SendNetworkUpdateImmediate();
                waterbikes.Remove(_snowmobile);
            }

            private void InitBuoyancy()
            {
                _buoyancy = _snowmobile.gameObject.AddComponent<Buoyancy>();

                _buoyancy.forEntity = _snowmobile;
                _buoyancy.rigidBody = _rigidbody;

                _buoyancy.doEffects = true;

                _buoyancy.requiredSubmergedFraction = 0f;

                _buoyancy.useUnderwaterDrag = true;
                _buoyancy.underwaterDrag = 20f;

                _buoyancy.waveHeightScale = 500f;

                var points = new BuoyancyPoint[config.BuoyancyPoints.Length];

                parentPoint = new GameObject("buoyancy");

                for (var i = 0; i < points.Length; i++)
                {
                    var go = new GameObject($"buoyancyPoint_{i}");

                    go.transform.SetParent(parentPoint.transform, false);
                    go.transform.localPosition = config.BuoyancyPoints[i].Position;

                    var point = go.AddComponent<BuoyancyPoint>();

                    point.buoyancyForce = config.buoyancyForce;
                    point.size = config.BuoyancyPoints[i].Size;
                    points[i] = point;
                }

                parentPoint.transform.SetParent(_snowmobile.transform, false);
                parentPoint.transform.localPosition = new Vector3(0.046f, -0.15f, -0.853f);

                _buoyancy.points = points;
            }

            void FixedUpdate()
            {
                if (Time.frameCount - framesSinceLastControl >= 7)
                {
                    ProcessPlayerInput();
                    framesSinceLastControl = Time.frameCount;
                }

                var isInWater = WaterLevel.Test(thrustPoint.transform.position, true, _snowmobile);
                if (isInWater)
                {
                    framesSinceLastInWater = 0;
                }
                else
                {
                    framesSinceLastInWater += 1;
                }

                framesSinceLastFlip += 1;
                if (config.autoFlip && IsFlipped() && framesSinceLastFlip > 30f && isInWater)
                {
                    Flip();
                    framesSinceLastFlip = 0;
                    return;
                }

                if (IsFlipped() && _snowmobile.engineController.IsOn)
                {
                    _snowmobile.engineController.StopEngine();
                    Flip();
                    return;
                }
                _snowmobile.SetFlag(BaseEntity.Flags.Reserved7, _rigidbody.IsSleeping() && !_snowmobile.AnyMounted(), false, true);
                if (!_snowmobile.engineController.IsOn)
                {
                    gasPedal = 0f;
                    steering = 0f;
                }
                _snowmobile.SetFlag(BaseEntity.Flags.Reserved7, _rigidbody.IsSleeping() && !_snowmobile.AnyMounted(), false, true);

                if (gasPedal != 0f && isInWater && _buoyancy.submergedFraction > 0.3f)
                {
                    var force = (transform.forward + (transform.right * steering * config.steeringScale)).normalized * gasPedal * (boosting ? config.boostButtonThrust : config.engineThrust);
                    _rigidbody.AddForceAtPosition(force, thrustPoint.transform.position, ForceMode.Force);
                    _snowmobile.engineKW = 65;
                }
                else
                {
                    _snowmobile.engineKW = config.Allow_To_Move_On_Land ? config.engineThrustOnLand : 1;
                }

                if (!config.slowlyOnGrass || framesSinceLastInWater < 100 || TerrainMeta.TopologyMap.GetTopology(_snowmobile.transform.position, OCEANSIDE_TOPOLOGY))
                {
                    _rigidbody.drag = 0.2f + (0.6f * Mathf.InverseLerp(0f, 1f, _buoyancy.submergedFraction));
                    _rigidbody.angularDrag = 0.5f + (0.005f * Mathf.InverseLerp(0f, 2f, _rigidbody.velocity.SqrMagnitude2D()));
                }

                parentPoint.transform.rotation = _snowmobile.transform.rotation;
                if (config.offAxisDrag > 0f)
                {
                    var value2 = Vector3.Dot(transform.forward, _rigidbody.velocity.normalized);
                    var num2 = Mathf.InverseLerp(0.98f, 0.92f, value2);
                    _rigidbody.drag += num2 * config.offAxisDrag * _buoyancy.submergedFraction;
                }

                var x = Mathf.InverseLerp(1f, 10f, _rigidbody.velocity.Magnitude2D()) * 0.5f * _snowmobile.healthFraction;

                if (!_snowmobile.engineController.IsOn)
                {
                    x = 0f;
                }

                var y = 1f - (0.3f * (1f - _snowmobile.healthFraction));

                _buoyancy.buoyancyScale = (1f + x) * y;
            }


            public void ProcessPlayerInput()
            {
                if (_snowmobile == null || _snowmobile.IsDestroyed)
                {
                    return;
                }

                if (!_snowmobile.AnyMounted())
                {
                    return;
                }

                var driver = _snowmobile.GetDriver();
                var inputState = driver?.serverInput;

                if (driver == null || inputState == null)
                {
                    return;
                }

                if (inputState.IsDown(BUTTON.SPRINT) && !boosting && !boostCooldown && config.enableBoostButton)
                {
                    boosting = true;
                    boostCooldown = true;
                    Instance.timer.Once(config.boostDuration, () => { boosting = false; });
                    Instance.timer.Once(config.boostCooldown, () => { boostCooldown = false; });
                    SendEffect("assets/prefabs/tools/pager/effects/beep.prefab", driver, transform.position);
                }


                if (inputState.IsDown(BUTTON.FORWARD))
                {
                    gasPedal = 1f;
                }
                else if (inputState.IsDown(BUTTON.BACKWARD))
                {
                    gasPedal = -0.5f;
                }
                else
                {
                    gasPedal = 0f;
                }

                if (inputState.IsDown(BUTTON.LEFT))
                {
                    steering = 1f;
                    return;
                }

                if (inputState.IsDown(BUTTON.RIGHT))
                {
                    steering = -1f;
                    return;
                }
                steering = 0f;
            }

            public bool IsFlipped()
            {
                return Vector3.Dot(Vector3.up, transform.up) <= 0f;
            }

            public void Flip()
            {
                _rigidbody.AddRelativeTorque(Vector3.right * 4f, ForceMode.VelocityChange);
                _rigidbody.AddForce(Vector3.up * 4f, ForceMode.VelocityChange);
            }
        }
        #endregion

        #region Hooks
        void Init()
        {
            Instance = this;
            waterbikes = new Dictionary<BaseNetworkable, WaterBikeComponent>();
            playerWaterbikes = new Dictionary<BasePlayer, Snowmobile>();
            cooldownList = Facepunch.Pool.GetList<BasePlayer>();

            permission.RegisterPermission(ADMIN_PERMISSION, this);
            permission.RegisterPermission(SPAWN_PERMISSION, this);
            permission.RegisterPermission(FREE_PERMISSION, this);
            permission.RegisterPermission(DESPAWN_PERMISSION, this);
            permission.RegisterPermission(BUY_PERMISSION, this);
        }

        void Unload()
        {
            foreach (var obj in UnityEngine.Object.FindObjectsOfType<WaterBikeComponent>())
            {
                UnityEngine.Object.DestroyImmediate(obj);
            }

            waterbikes = null;
            playerWaterbikes = null;
            Pool.FreeList(ref cooldownList);
            config = null;
            Instance = null;
        }

        object CanBuild(Planner plan, Construction prefab, Construction.Target target)
        {
            if (plan == null)
            {
                return null;
            }

            var item = plan.GetItem();
            if (item == null)
            {
                return null;
            }

            var player = plan.GetOwnerPlayer();
            if (player == null)
            {
                return null;
            }

            if (!(item.info.itemid == config.ItemID && item.skin == config.ItemSkinID))
            {
                return null;
            }

            if (config.AllowOnlyOneWaterBikePerPlayer && playerWaterbikes.ContainsKey(player) && playerWaterbikes[player] != null)
            {
                PrintToChat(player, lang.GetMessage("onlyOne", this, player.UserIDString));
                return false;
            }

            if (cooldownList.Contains(player))
            {
                PrintToChat(player, lang.GetMessage("Cooldown", this, player.UserIDString));
                return false;
            }

            if (config.spawnOnlyOnBeaches && !(TerrainMeta.TopologyMap.GetTopology(player.transform.position, BEACH_TOPOLOGY) || TerrainMeta.TopologyMap.GetTopology(player.transform.position, BEACHSIDE_TOPOLOGY)))
            {
                PrintToChat(player, lang.GetMessage("onlyBeach", this, player.UserIDString));
                return false;
            }

            return null;
        }


        void OnEntityBuilt(Planner plan, GameObject go)
        {
            if (plan == null)
            {
                return;
            }

            var item = plan.GetItem();
            if (item == null)
            {
                return;
            }

            var player = plan.GetOwnerPlayer();
            if (player == null)
            {
                return;
            }

            if (item.info.itemid == config.ItemID && item.skin == config.ItemSkinID)
            {
                StartCooldown(player);
                SpawnWaterbike(go.transform.position, go.transform.rotation, player, item.conditionNormalized);

                NextFrame(() =>
                {
                    go.GetComponent<BaseEntity>().AdminKill();
                });
            }
        }

        void OnServerInitialized(bool initial)
        {
            var count = 0;

            foreach (var ent in BaseNetworkable.serverEntities)
            {
                if (!(ent is Snowmobile))
                {
                    continue;
                }

                if ((config.Make_All_Snowmobiles_Waterbikes || (ent as BaseEntity).HasFlag(BaseEntity.Flags.Reserved10)) && !waterbikes.ContainsKey(ent))
                {
                    ent.gameObject.AddComponent<WaterBikeComponent>();
                    var snowmobile = ent as Snowmobile;
                    if (snowmobile.OwnerID != 0)
                    {
                        var player = BasePlayer.FindByID(snowmobile.OwnerID);
                        if (player == null)
                        {
                            continue;
                        }

                        if (playerWaterbikes.ContainsKey(player))
                        {
                            playerWaterbikes[player] = snowmobile;
                        }
                        else
                        {
                            playerWaterbikes.Add(player, snowmobile);
                        }
                    }
                    count++;
                }
            }

            Puts($"Loaded {count} waterbikes");
        }

        void OnEngineStarted(BaseVehicle vehicle, BasePlayer driver)
        {
            if (driver == null || vehicle == null)
            {
                return;
            }

            if (!(vehicle is Snowmobile))
            {
                return;
            }

            if (!waterbikes.ContainsKey(vehicle))
            {
                return;
            }

            if (config.enableBoostButton)
            {
                driver.ShowToast(GameTip.Styles.Blue_Normal, lang.GetMessage("boostToast", this, driver.UserIDString));
            }

            if (config.Allow_To_Move_On_Land)
            {
                return;
            }

            if (!WaterLevel.Test(waterbikes[vehicle].thrustPoint.transform.position, true, vehicle))
            {
                timer.Once(0.1f, () =>
                {
                    if (vehicle != null)
                    {
                        (vehicle as Snowmobile).engineController.StopEngine();
                    }
                });
            }
        }

        void OnEntitySpawned(BaseNetworkable entity)
        {
            if (!(entity is Snowmobile))
            {
                return;
            }

            if (lastKilledSnowmobilePos == entity.transform.position)
            {
                entity.gameObject.AddComponent<WaterBikeComponent>();
                lastKilledSnowmobilePos = new Vector3();
                return;
            }

            if (!config.Make_All_Snowmobiles_Waterbikes)
            {
                return;
            }

            if (waterbikes.ContainsKey(entity))
            {
                return;
            }

            entity.gameObject.AddComponent<WaterBikeComponent>();
        }

        void OnEntityKill(BaseNetworkable entity)
        {
            if (entity == null)
            {
                return;
            }

            if (!waterbikes.ContainsKey(entity))
            {
                return;
            }

            lastKilledSnowmobilePos = entity.transform.position;
            var snowmobile = entity as Snowmobile;

            if (!playerWaterbikes.ContainsValue(snowmobile))
            {
                return;
            }

            var player = BasePlayer.FindByID(snowmobile.OwnerID);
            if (player != null)
            {
                playerWaterbikes.Remove(player);
            }
        }

        void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            if (!cooldownList.Contains(player))
            {
                return;
            }

            cooldownList.Remove(player);
        }

        object CanMountEntity(BasePlayer player, BaseMountable seat)
        {
            if (seat?.parentEntity == null)
            {
                return null;
            }

            var entity = seat.parentEntity.Get(true);

            if (entity == null || entity.IsDestroyed || !waterbikes.ContainsKey(entity))
            {
                return null;
            }

            var activeItem = player.GetActiveItem();

            if (((!config.Allow_Pickup_Only_In_Building_Privilege && !player.IsBuildingBlocked()) ||
                (config.Allow_Pickup_Only_In_Building_Privilege && player.IsBuildingAuthed())) &&
                activeItem != null && activeItem.info.itemid == HAMMER_ITEMID)
            {
                var condition = entity.Health() / entity.MaxHealth() * 100f;

                player.GiveItem(CreateItem(1, condition - config.HP_Reduction), BaseEntity.GiveItemReason.PickedUp);
                entity.AdminKill();
                return false;
            }

            return null;
        }
        #endregion

        #region Methods
        public Vector3 GetSpawnPosition(BasePlayer player)
        {
            RaycastHit hit;
            Vector3 position;
            if (Physics.Raycast(player.eyes.position, player.eyes.HeadForward(), out hit, 15f))
            {
                position = hit.point + new Vector3(0, 1.2f, 0);
            }
            else
            {
                position = player.transform.position + new Vector3(0, 0.2f, 0);
            }

            return position;
        }

        public void StartCooldown(BasePlayer player)
        {
            if (player == null)
            {
                return;
            }

            if (config.Cooldown <= 0)
            {
                return;
            }

            if (cooldownList.Contains(player))
            {
                return;
            }

            cooldownList.Add(player);

            timer.Once(config.Cooldown, () =>
            {
                if (cooldownList.Contains(player))
                {
                    cooldownList.Remove(player);
                }
            });
        }

        public static void WriteLine(BasePlayer player, string message)
        {
            if (player == null)
            {
                Instance.Puts(message);
                return;
            }
            Instance.PrintToConsole(player, $"[{Instance.Name}] " + message);
        }

        public static void SendEffect(string effectPath, BasePlayer player, Vector3 position)
        {
            if (player == null)
            {
                return;
            }

            if (!Net.sv.IsConnected())
            {
                return;
            }

            var effect = new Effect(effectPath, position, position);
            effect.pooledstringid = StringPool.Get(effect.pooledString);

            var netWrite = Net.sv.StartWrite();
            netWrite.PacketID(Message.Type.Effect);
            effect.WriteToStream(netWrite);
            netWrite.Send(new SendInfo(player.net.connection));
        }

        public Item CreateItem(int amount = 1, float condition = 100f)
        {
            var item = ItemManager.CreateByItemID(config.ItemID, amount, config.ItemSkinID);
            item.name = config.ItemName;
            item.condition = condition;
            return item;
        }
        #endregion

        #region Console Commands
        [ConsoleCommand("givewaterbike")]
        void GiveWaterbikeCCmd(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();

            if (player != null && !permission.UserHasPermission(player.UserIDString, ADMIN_PERMISSION))
            {
                WriteLine(player, "You don't have permission to run this console command!");
                return;
            }

            var args = arg.Args;
            if (args == null || args?.Length == 0)
            {
                WriteLine(player, "Usage: givewaterbike <amount> <player name>");
                return;
            }

            var amount = 1;
            var skips_first_arg = false;

            if (arg.Args[0].IsNumeric() && arg.Args.Length > 1)
            {
                amount = Convert.ToInt32(arg.Args[0]);
                skips_first_arg = true;
            }

            var target = BasePlayer.Find(string.Join(" ", skips_first_arg ? arg.Args.Skip(1) : arg.Args));
            if (target == null)
            {
                WriteLine(player, "Player not found!");
                return;
            }

            target.GiveItem(CreateItem(amount));
            PrintToChat(target, lang.GetMessage("waterbikeGiven", this, target.UserIDString));

            WriteLine(player, $"{amount} water bike(s) were given to " + target.displayName);
        }
        #endregion

        #region Chat Commands
        [ChatCommand("waterbike_debug")]
        private void WaterbikeDebugCommand(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, ADMIN_PERMISSION))
            {
                PrintToChat(player, lang.GetMessage("NoPermission", this, player.UserIDString));
                return;
            }
            var vehicle = player.GetMountedVehicle();

            if (vehicle == null || !waterbikes.ContainsKey(vehicle))
            {
                PrintToChat(player, lang.GetMessage("NoWaterbike", this, player.UserIDString));
                return;
            }

            var buoy = vehicle.gameObject.GetComponent<Buoyancy>();
            var waterbike = waterbikes[vehicle];

            PrintToChat(player, lang.GetMessage("Showing", this, player.UserIDString));

            foreach (var point in buoy.points)
            {
                player.SendConsoleCommand("ddraw.text", 30f, Color.green, point.transform.position, $"<size=13>Force - {point.buoyancyForce}\nSize = {point.size}</size>");
                player.SendConsoleCommand("ddraw.box", 30f, Color.green, point.transform.position, point.size);
            }

            player.SendConsoleCommand("ddraw.box", 30f, Color.blue, waterbike.thrustPoint.transform.position, 0.1f);
            player.SendConsoleCommand("ddraw.text", 30f, Color.blue, waterbike.thrustPoint.transform.position, "<size=13>Thrust point</size>");
        }


        [ChatCommand("buywaterbike")]
        void BuyWaterbikeCommand(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, BUY_PERMISSION))
            {
                PrintToChat(player, lang.GetMessage("NoPermission", this, player.UserIDString));
                return;
            }

            var notEnoughMsg = lang.GetMessage("NotEnough", this, player.UserIDString);

            if (config.Price.TryPaying(player, FREE_PERMISSION, notEnoughMsg, notEnoughMsg))
            {
                player.GiveItem(CreateItem(config.AmountPerBuy));
                PrintToChat(player, lang.GetMessage("waterbikeGiven", this, player.UserIDString));
            }
        }

        [ChatCommand("waterbike")]
        private void WaterbikeCommand(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, SPAWN_PERMISSION))
            {
                PrintToChat(player, lang.GetMessage("NoPermission", this, player.UserIDString));
                return;
            }

            if (args.Length == 1 && args[0].ToLower() == "remove")
            {
                if (!permission.UserHasPermission(player.UserIDString, DESPAWN_PERMISSION))
                {
                    PrintToChat(player, lang.GetMessage("NoPermission", this, player.UserIDString));
                    return;
                }

                if (config.AllowOnlyOneWaterBikePerPlayer)
                {
                    if (!playerWaterbikes.ContainsKey(player) || playerWaterbikes[player] == null)
                    {
                        PrintToChat(player, lang.GetMessage("waterbikeDoesntExist", this, player.UserIDString));
                        return;
                    }

                    playerWaterbikes[player].DismountAllPlayers();
                    playerWaterbikes[player].Kill(BaseNetworkable.DestroyMode.Gib);
                    PrintToChat(player, lang.GetMessage("removed", this, player.UserIDString));
                    return;
                }

                RaycastHit despawn_hit;
                if (Physics.Raycast(player.eyes.position, player.eyes.HeadForward(), out despawn_hit, 15f))
                {
                    var hit_ent = despawn_hit.GetEntity();
                    if (hit_ent != null && hit_ent is Snowmobile && waterbikes.ContainsKey(hit_ent))
                    {
                        hit_ent.Kill(BaseNetworkable.DestroyMode.Gib);
                        PrintToChat(player, lang.GetMessage("removed", this, player.UserIDString));
                        return;
                    }
                }
                PrintToChat(player, lang.GetMessage("lookat", this, player.UserIDString));
                return;
            }

            if (config.AllowOnlyOneWaterBikePerPlayer && playerWaterbikes.ContainsKey(player) && playerWaterbikes[player] != null)
            {
                PrintToChat(player, lang.GetMessage("onlyOne", this, player.UserIDString));
                return;
            }

            if (cooldownList.Contains(player))
            {
                PrintToChat(player, lang.GetMessage("Cooldown", this, player.UserIDString));
                return;
            }

            if (config.spawnOnlyOnBeaches && !(TerrainMeta.TopologyMap.GetTopology(player.transform.position, BEACH_TOPOLOGY) || TerrainMeta.TopologyMap.GetTopology(player.transform.position, BEACHSIDE_TOPOLOGY)))
            {
                PrintToChat(player, lang.GetMessage("onlyBeach", this, player.UserIDString));
                return;
            }

            RaycastHit hit;
            BaseEntity ent = null;

            if (Physics.Raycast(player.eyes.position, player.eyes.HeadForward(), out hit, 15f))
            {
                var hit_ent = hit.GetEntity();
                if (hit_ent != null && hit_ent is Snowmobile && !waterbikes.ContainsKey(hit_ent))
                {
                    ent = hit_ent;
                }
            }

            var notEnoughMsg = lang.GetMessage("NotEnough", this, player.UserIDString);

            if (config.Price.TryPaying(player, FREE_PERMISSION, notEnoughMsg, notEnoughMsg))
            {
                if (ent != null)
                {
                    ent.gameObject.AddComponent<WaterBikeComponent>();
                    PrintToChat(player, lang.GetMessage("Converted", this, player.UserIDString));
                }
                else
                {
                    SpawnWaterbike(GetSpawnPosition(player), player.eyes.rotation, player);
                    StartCooldown(player);
                    PrintToChat(player, lang.GetMessage("Spawned", this, player.UserIDString));
                }

                return;
            }
        }
        #endregion

        #region API
        [HookMethod("SpawnWaterbike")]
        public BaseEntity SpawnWaterbike(Vector3 position, Quaternion rotation, BasePlayer ownerPlayer = null, float hp_fraction = 1f)
        {
            var waterBike = GameManager.server.CreateEntity(config.WaterbikePrefab, position, rotation) as Snowmobile;
            waterBike.gameObject.AddComponent<WaterBikeComponent>();
            waterBike.Spawn();

            if (config.AllowOnlyOneWaterBikePerPlayer && ownerPlayer != null)
            {
                waterBike.OwnerID = ownerPlayer.userID;
                playerWaterbikes.Add(ownerPlayer, waterBike);
            }

            if (config.startingFuel > 0)
            {
                waterBike.GetFuelSystem().AddStartingFuel(config.startingFuel);
            }

            waterBike.health *= hp_fraction;

            waterBik
// ... [Code preview truncated due to length. Full source in attached file] ...

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

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

Сверху