• File: TopTurret.cs
  • Full Path: /var/www/FileManager/Files/RUST PLUGINS/TopTurret.cs
  • Date Modified: 04/27/2025 8:55 AM
  • File size: 21.77 KB
  • MIME-type: text/plain
  • Charset: utf-8
 
Open Back
using System;
using System.Collections.Generic;
using Oxide.Core;
using UnityEngine;
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System.Collections;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Rust;
using VLB;
using System.Threading;

namespace Oxide.Plugins
{
    [Info("TopTurret", "Sempai#3239", "1.1.1")]
    class TopTurret : RustPlugin
    {
        static TopTurret ins;
        PluginConfig config;

        public class PluginConfig
        {
            [JsonProperty("Максимум хп турели")]
            public float MaxHealth;

            [JsonProperty("Радиус агра турели (100 стандарт)")]
            public float aggroRange;

            [JsonProperty("Угол разлета пуль (4 - стандарт (чем меньше тем точнее))")]
            public float AimCone;

            [JsonProperty("Интервал между запусками ракет")]
            public float FireRate;

            [JsonProperty("Перезарядка между залпами")]
            public float ReloadTime;

            [JsonProperty("Множитель урона наносимый ракетами (1 - стандарт)")]
            public float damage;
            [JsonProperty("Радиус взрыва от ракеты (3 дефолт)")]
            public float radius;

            [JsonProperty("Максимум турелей у игрока (0 - безлимит)")]
            public int MaxCount;
        }

        protected override void LoadDefaultConfig()
        {
            config = new PluginConfig
            {
                MaxHealth = 1500,
                AimCone = 4,
                aggroRange = 100,
                FireRate = 0.3f,
                ReloadTime = 15f,
                damage = 0.6f,
                radius = 3f,
                MaxCount = 4
            };
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            config = Config.ReadObject<PluginConfig>();
        }

        protected override void SaveConfig()
        {
            Config.WriteObject(config);
        }

        public DataStorage dataStorage;
        public class DataStorage
        {
            public List<ulong> netID = new List<ulong>();
            public Dictionary<ulong, int> turrentID = new Dictionary<ulong, int>();
        }
        void LoadData()
        {
            dataStorage = new DataStorage() { netID = new List<ulong>(), turrentID = new Dictionary<ulong, int>() };
            if (Interface.Oxide.DataFileSystem.ExistsDatafile("TopTurret"))
            {
                dataStorage = Interface.Oxide.DataFileSystem.ReadObject<DataStorage>("TopTurret");
            }
            else
            {
                Interface.Oxide.DataFileSystem.WriteObject("TopTurret", dataStorage);
            }
        }

        private void OnServerInitialized()
        {
            ins = this;
            LoadConfig();
            LoadData();
            timer.Once(10f, () => RestoreTurret());
        }

        void Unload()
        {
            Interface.Oxide.DataFileSystem.WriteObject("TopTurret", dataStorage);
            var objects = UnityEngine.Object.FindObjectsOfType<TurretComponent>();
            foreach (var obj in objects)
                if (obj != null)
                    UnityEngine.Object.Destroy(obj);
        }

        void OnServerSave()
        {
            Interface.Oxide.DataFileSystem.WriteObject("TopTurret", dataStorage);
        }
        private bool TryGetPlayerView(BasePlayer player, out Quaternion viewAngle)
        {
            viewAngle = new Quaternion(0f, 0f, 0f, 0f);
            if (player.serverInput?.current == null) return false;
            viewAngle = Quaternion.Euler(player.serverInput.current.aimAngles);
            return true;
        }

        private void OnPlayerInput(BasePlayer player, InputState input)
        {
            if (!input.WasJustPressed(BUTTON.RELOAD)) return;

            new Thread(new ThreadStart(delegate 
            {
                Vector3 eyesPosition = new Vector3(0f, 0.9f, 0f);
                Quaternion currentRot;
                TryGetPlayerView(player, out currentRot);
                var hitpoints = Physics.RaycastAll(new Ray(player.transform.position + eyesPosition, currentRot * Vector3.forward), 5f);
                Array.Sort(hitpoints, (a, b) => a.distance == b.distance ? 0 : a.distance > b.distance ? 1 : -1);
                for (var i = 0; i < hitpoints.Length; i++)
                {
                    var turret = hitpoints[i].collider.GetComponentInParent<NPCAutoTurret>();
                    if (turret != null && turret.GetComponent<TurretComponent>() != null)
                    {
                        if (turret.authorizedPlayers.Any(x => x.userid == player.userID))
                        {
                            if (Vector3.Distance(turret.transform.position, player.transform.position) > 2) return;
                            turret.GetComponent<TurretComponent>().ToggleTurret();
                            break;
                        }
                    }
                }
            })).Start();
            
        }

        object OnCupboardAuthorize(BuildingPrivlidge privilege, BasePlayer player)
        {
            if (privilege == null || player == null)
                return null;
            if (privilege.GetBuilding().decayEntities.Any(x => x.ShortPrefabName.Contains("sentry.scientist.static")))
            {
                var turret = privilege.GetBuilding().decayEntities.Where(x => x.ShortPrefabName.Contains("sentry.scientist.static"));
                foreach (var it in turret)
                {
                    if (it.GetComponent<AutoTurret>().authorizedPlayers.Any(x => x.userid == player.userID)) continue;
                    it.GetComponent<AutoTurret>().authorizedPlayers.Add(new ProtoBuf.PlayerNameID() { userid = player.userID, username = player.displayName, ShouldPool = true });
                    it.GetComponent<AutoTurret>().SendNetworkUpdate();
                }
            }
            return null;
        }
        object OnCupboardDeauthorize(BuildingPrivlidge privilege, BasePlayer player)
        {
            if (privilege == null || player == null)
                return null;
            if (privilege.GetBuilding().decayEntities.Any(x => (x as BaseEntity).ShortPrefabName.Contains("sentry.scientist.static")))
            {
                var turret = privilege.GetBuilding().decayEntities.Where(x => x.ShortPrefabName == "sentry.scientist.static");
                foreach (var it in turret)
                {
                    if (it.GetComponent<AutoTurret>().authorizedPlayers.Any(x => x.userid != player.userID)) continue;
                    it.GetComponent<AutoTurret>().authorizedPlayers.Remove(it.GetComponent<AutoTurret>().authorizedPlayers.First(x => x.userid == player.userID));
                    it.GetComponent<AutoTurret>().SendNetworkUpdate();
                }
            }
            return null;
        }

        void RestoreTurret()
        {
            var ents = UnityEngine.Object.FindObjectsOfType<NPCAutoTurret>().Where(x => x.OwnerID != 0);

            foreach (var turret in ents)
            {
                if (dataStorage.netID.Contains(turret.net.ID.Value))
                {
                    if (turret.IsDestroyed)
                    {
                        dataStorage.netID.Remove(turret.net.ID.Value);
                        continue;
                    }
                    turret.GetOrAddComponent<TurretComponent>();
                    SetupProtection(turret);

                    turret.InitializeHealth(turret.health < 1000 ? turret.health : config.MaxHealth, config.MaxHealth);
                    turret.SendNetworkUpdate();
                }
            }
        }

        void SpawnTurret(Vector3 pos, Quaternion rot, ulong owner, float health)
        {
            NPCAutoTurret turret = GameManager.server.CreateEntity("assets/content/props/sentry_scientists/sentry.scientist.static.prefab", pos, rot) as NPCAutoTurret;
            turret.OwnerID = owner;
            turret.Spawn();
            turret.InitializeHealth(health < 1000 ? health : config.MaxHealth, config.MaxHealth);
            turret.gameObject.AddComponent<TurretComponent>();
            turret.enableSaving = true;
            turret.SetIsOnline(false);
            turret.SetPeacekeepermode(false);
            SetupProtection(turret);
            turret.SendNetworkUpdate();
            dataStorage.netID.Add(turret.net.ID.Value);
            OnServerSave();
        }

        private void SetupProtection(BaseCombatEntity turret)
        {
            turret.baseProtection = ScriptableObject.CreateInstance<ProtectionProperties>();
            turret.baseProtection.amounts = new float[]
            {
                    1,1,1,1,1,0.8f,1,1,1,0.9f,0.5f,
                    0.5f,1,1,0,0.5f,0,1,1,0,1,0.9f
            };
        }
        [ConsoleCommand("TopTurret")]
        void SetTurret(ConsoleSystem.Arg arg)
        {
            if (arg.Connection != null && arg.Connection.authLevel < 2)
                return;
            if (arg.Args == null || arg.Args.Length < 2)
            {
                Puts("Use: TopTurret STEAMID amount");
                return;
            }
            ulong uid = arg.GetUInt64(0);
            int amount = arg.GetInt(1);
            BasePlayer player = BasePlayer.FindByID(uid);
            var item = ItemManager.CreateByName("autoturret", amount, 1756027229);
            item.name = "TopTurret";
            player.GiveItem(item, BaseEntity.GiveItemReason.PickedUp);
            SendReply(player, "Вы получили TopTurret");
        }

        object OnEntityBuilt(Planner plan, GameObject obj)
        {
            var entity = obj.GetComponent<BaseEntity>();
            if (plan == null) return null;

            if (entity != null && entity.PrefabName == "assets/prefabs/npc/autoturret/autoturret_deployed.prefab" && entity.skinID == 1756027229)
            {
                BasePlayer player = plan.GetOwnerPlayer();
                if (player == null) return null;
                if (config.MaxCount > 0 && !player.IsAdmin)
                {
                    if (!dataStorage.turrentID.ContainsKey(player.userID))
                        dataStorage.turrentID.Add(player.userID, 1);
                    else if (dataStorage.turrentID.ContainsKey(player.userID) && dataStorage.turrentID[player.userID] < config.MaxCount)
                        dataStorage.turrentID[player.userID]++;
                    else if (dataStorage.turrentID.ContainsKey(player.userID) && dataStorage.turrentID[player.userID] >= config.MaxCount)
                    {
                        SendReply(player, "Достигнут лимит установку TopTurret");
                        var item = ItemManager.CreateByName("autoturret", 1, 1756027229);
                        item.name = "TopTurret";
                        item.condition = entity.Health() / entity.MaxHealth() * 100;
                        player.GiveItem(item, BaseEntity.GiveItemReason.PickedUp);

                        entity.Kill();
                        return false;
                    }
                }
                var pos = entity.transform.position;
                var rot = entity.transform.rotation;

                try
                {
                    SpawnTurret(pos, rot, player.userID, entity.Health());
                }
                catch (Exception ex)
                {
                    Puts(ex.Message);
                    //SpawnTurret(pos, rot, player.userID, 100f);
                }
                NextTick(() => entity.Kill());
                //SendReply(player, $"Вы установили TopTurret. Вы можете установить еще {dataStorage.turrentID[player.userID] - config.MaxCount}");
            }
            return null;
        }

        object CanPickupEntity(BasePlayer player, BaseCombatEntity entity)
        {
            if (entity.ShortPrefabName.Contains("sentry.scientist"))
            {
                if (dataStorage.turrentID.ContainsKey(entity.OwnerID) && dataStorage.turrentID[entity.OwnerID] > 0)
                    dataStorage.turrentID[entity.OwnerID]--;
                if (dataStorage.netID.Contains(entity.net.ID.Value)) dataStorage.netID.Remove(entity.net.ID.Value);
                entity.skinID = 1756027229;
            }
            return true;
        }

        void OnEntityDeath(BaseCombatEntity entity, HitInfo info)
        {
            try
            {
                if (entity?.net?.ID == null) return;
                if (dataStorage.netID.Contains(entity.net.ID.Value))
                    dataStorage.netID.Remove(entity.net.ID.Value);
            }
            catch { }
        }

        void OnEntityKill(BaseNetworkable entity)
        {
            try
            {
                if (entity == null) return;
                if (entity.net == null) return;
                if (dataStorage == null) return;
                if (dataStorage.netID.Contains(entity.net.ID.Value))
                    dataStorage.netID.Remove(entity.net.ID.Value);
            }
            catch { }
        }

        public class TurretComponent : FacepunchBehaviour
        {
            AutoTurret turret;
            private DestroyOnGroundMissing destroyOnGroundMissing;
            private GroundWatch groundWatch;
            private SphereCollider sphereCollider;
            Dictionary<BasePlayer, bool> ColliderPlayersList = new Dictionary<BasePlayer, bool>();
            ulong netID;
            ulong ownerid;
            private void Awake()
            {
                turret = gameObject.GetComponent<AutoTurret>();
                netID = turret.net.ID.Value;
                ownerid = turret.OwnerID;
                destroyOnGroundMissing = gameObject.GetComponent<DestroyOnGroundMissing>();
                if (destroyOnGroundMissing == null)
                {
                    gameObject.AddComponent<DestroyOnGroundMissing>();
                    destroyOnGroundMissing = gameObject.GetComponent<DestroyOnGroundMissing>();
                }
                groundWatch = gameObject.GetComponent<GroundWatch>();
                if (groundWatch == null)
                {
                    gameObject.AddComponent<GroundWatch>();
                    groundWatch = gameObject.GetComponent<GroundWatch>();
                }
                groundWatch.CancelInvoke("OnPhysicsNeighbourChanged");
                groundWatch.InvokeRepeating("OnPhysicsNeighbourChanged", 0, 0.5f);

                turret.sightRange = ins.config.aggroRange;
                turret.aimCone = ins.config.AimCone;

                this.sphereCollider = gameObject.AddComponent<SphereCollider>();
                this.sphereCollider.name = $"ArtefactRadZone.{turret.net.ID}";
                this.sphereCollider.transform.position = turret.transform.position;
                this.sphereCollider.gameObject.layer = (int)Rust.Layer.Reserved1;
                this.sphereCollider.isTrigger = true;
                this.sphereCollider.radius = 3f;
                InvokeRepeating("DrawInfoPlayer", 0f, 1f);
                InvokeRepeating("ChectTarget", 0, 0.2f);
            }

            public void ToggleTurret()
            {
                if (turret.IsOnline())
                {
                    turret.SetIsOnline(false);
                }
                else
                    turret.SetOnline();
            }

            private void OnTriggerEnter(Collider other)
            {
                var target = other.GetComponentInParent<BasePlayer>();
                if (target != null && !ColliderPlayersList.ContainsKey(target))
                    ColliderPlayersList.Add(target, !target.IsAdmin);
            }

            private void OnTriggerExit(Collider other)
            {
                var target = other.GetComponentInParent<BasePlayer>();
                if (target != null && ColliderPlayersList.ContainsKey(target))
                    ColliderPlayersList.Remove(target);
            }

            void DrawInfoPlayer()
            {
                foreach (var player in ColliderPlayersList)
                {
                    if (!turret.authorizedPlayers.Any(x => x.userid == player.Key.userID)) continue;
                    if (player.Value) SetPlayerFlag(player.Key, BasePlayer.PlayerFlags.IsAdmin, true);
                    player.Key.SendConsoleCommand("ddraw.text", 1.01f, UnityEngine.Color.white, turret.transform.position + Vector3.up, $"<size=16>{(turret.IsOnline() ? "Нажмите R чтобы <color=red>ВЫКЛЮЧИТЬ</color> турель" : "Нажмите R чтобы <color=green>ВКЛЮЧИТЬ</color> турель")}</size>");
                    if (player.Value) SetPlayerFlag(player.Key, BasePlayer.PlayerFlags.IsAdmin, false);
                }
            }

            private float lastFireMG;
            private int LaunchPos = 1;
            void ChectTarget()
            {
                if (turret.HasTarget())
                {
                    var Distance = Vector3.Distance(turret.transform.position, turret.target.transform.position);
                    if (Distance < 5) return;
                    if (Time.realtimeSinceStartup >= lastFireMG)
                    {
                        var targetPos = turret.aimDir;
                        if (LaunchPos == 1)
                        {
                            Vector3 pos = turret.gun_yaw.transform.position;
                            CreateRocket(pos, targetPos, 3.0f / Distance);

                            lastFireMG = Time.realtimeSinceStartup + ins.config.FireRate;
                            LaunchPos++;
                        }
                        else if (LaunchPos == 2)
                        {
                            Vector3 pos2 = turret.gun_yaw.transform.position;
                            CreateRocket(pos2, targetPos, 3.0f / Distance);

                            lastFireMG = Time.realtimeSinceStartup + ins.config.FireRate;
                            LaunchPos++;
                        }
                        else if (LaunchPos == 3)
                        {
                            Vector3 pos2 = turret.gun_yaw.transform.position;
                            CreateRocket(pos2, targetPos, 3.0f / Distance);

                            lastFireMG = Time.realtimeSinceStartup + ins.config.FireRate;
                            LaunchPos++;
                        }
                        else if (LaunchPos == 4)
                        {
                            Vector3 pos2 = turret.gun_yaw.transform.position;
                            CreateRocket(pos2, targetPos, 3.0f / Distance);

                            lastFireMG = Time.realtimeSinceStartup + ins.config.ReloadTime;
                            LaunchPos = 1;
                        }
                    }
                }

            }
            private void CreateRocket(Vector3 startPoint, Vector3 direction, float gravity)
            {
                ItemDefinition projectileItem = ItemManager.FindItemDefinition("ammo.rocket.hv");
                ItemModProjectile component = projectileItem.GetComponent<ItemModProjectile>();
                BaseEntity entity = GameManager.server.CreateEntity(component.projectileObject.resourcePath, startPoint, new Quaternion(), true);
                TimedExplosive timedExplosive = entity.GetComponent<TimedExplosive>();
                ServerProjectile serverProjectile = entity.GetComponent<ServerProjectile>();
                serverProjectile.gravityModifier = gravity;
                serverProjectile.speed = 200;
                timedExplosive.explosionRadius = ins.config.radius;
                timedExplosive.timerAmountMin = 30;
                timedExplosive.timerAmountMax = 30;
                ScaleAllDamage(timedExplosive.damageTypes, ins.config.damage);
                entity.SendMessage("InitializeVelocity", (object)(direction * 30f));
                entity.Spawn();
            }

            private void ScaleAllDamage(List<DamageTypeEntry> damageTypes, float scale)
            {
                for (int i = 0; i < damageTypes.Count; i++)
                    damageTypes[i].amount *= scale;
            }

            void SetPlayerFlag(BasePlayer player, BasePlayer.PlayerFlags f, bool b)
            {
                if (b)
                {
                    if (player.HasPlayerFlag(f)) return;
                    player.playerFlags |= f;
                }
                else
                {
                    if (!player.HasPlayerFlag(f)) return;
                    player.playerFlags &= ~f;
                }
                player.SendNetworkUpdateImmediate(false);
            }

            void Update()
            {
                CheckTarget();
            }

            void CheckTarget()
            {
                if (turret.target is SamSite)
                    turret.target = null;
            }


            private void OnDestroy()
            {
                if (ins.dataStorage.turrentID.ContainsKey(ownerid) && ins.dataStorage.turrentID[ownerid] > 0)
                    ins.dataStorage.turrentID[ownerid]--;
                if (ins.dataStorage.netID.Contains(netID))
                    ins.dataStorage.netID.Remove(netID);
                Destroy(this);
            }
        }

    }
}