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

FREE SecurityLights : 1.1.4 1.1.4

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
 /// <summary>
/// Author: S0N_0F_BISCUIT
/// Permissions:
///		securitylights.use - Allows players to use commands
///	Chat Commands:
///		/sl - Help information
///		/sl add - Converts the search light you are looking at to a security light
///		/sl remove - Converts the security light you are looking at to back to a search light
///		/sl mode <mode> - Sets the mode of the security light you are looking at
///		/sl globalmode <mode> - Sets the mode of all security lights you own
///		/sl info - Gives the owner the ability to check the status of a search light
///		/sl reloadconfig - Reloads the config file
///		<mode>
///			all - Targets players and helicopter
///			players - Targets players only
///			heli - Targets heli only
///		</mode>
/// </summary>
using System;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Core.Libraries.Covalence;
using Rust;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("SecurityLights", "S0N_0F_BISCUIT", "1.1.4", ResourceId = 2577)]
    [Description("Search light targeting system")]
    class SecurityLights : RustPlugin {
#region Variables
        /// <summary>
        /// References to other plugins
        /// </summary>
        [PluginReference]
        Plugin Clans, Friends, Vanish;
        /// <summary>
        /// Targeting mode for security lights
        /// </summary>
        public enum TargetMode {
            all, players, heli, lightshow
        }
        ;
        /// <summary>
        /// Configuration options
        /// </summary>
        class ConfigData {
            public int allDetectionRadius;
            public int allTrackingRadius;
            public int playerDetectionRadius;
            public int playerTrackingRadius;
            public int heliDetectionRadius;
            public int heliTrackingRadius;
            public bool autoConvert;
            public bool requireFuel;
            public bool nightOnly;
            public bool acquisitionSound;
            public bool targetFriends;
        }
        /// <summary>
        /// Data saved by the plugin
        /// </summary>
        class StoredData {
            public Dictionary<uint, TargetMode> Security_Lights {
                get;
                set;
            }
            = new Dictionary<uint, TargetMode>();
        }
        /// <summary>
        /// Main behaviour of security lights
        /// </summary>
        class SecurityLight : MonoBehaviour {
#region Variables
            private uint id;
            private SearchLight light {
                get;
                set;
            }
            = null;
            private TargetMode mode {
                get;
                set;
            }
            = TargetMode.all;
            public BaseCombatEntity target = null;
#endregion
#region Initialization
            /// <summary>
            /// Initialize security light
            /// </summary>
            private void Awake() {
                light = GetComponent<SearchLight>();
                id = light.net.ID;
                if (!instance.data.Security_Lights.ContainsKey(id)) instance.data.Security_Lights.Add(id, mode);
                mode = instance.data.Security_Lights[id];
                instance.securityLights.Add(this);
                instance.SaveData();
                gameObject.layer = (int)Layer.Reserved1;
                var collider = gameObject.GetComponent<SphereCollider>();
                if (collider != null) Destroy(collider);
                collider = gameObject.AddComponent<SphereCollider>();
                collider.center = Vector3.zero;
                collider.radius = instance.config.allDetectionRadius;
                collider.isTrigger = true;
                collider.enabled = true;
                ResetTarget();
            }
#endregion
#region Functionality
            /// <summary>
            /// New entity in range
            /// </summary>
            /// <param name="range"></param>
            private void OnTriggerEnter(Collider range) {
                BaseCombatEntity entity = range.GetComponentInParent<BaseCombatEntity>();
                // Check if entity is valid
                if (!IsValid(entity)) return;
                // Check for current target
                if (target != null) return;
                // Acquire new target
                if (ShouldTarget(entity)) SetTarget(entity);
            }
            /// <summary>
            /// Update entities within range
            /// </summary>
            /// <param name="range"></param>
            private void OnTriggerStay(Collider range) {
                BaseCombatEntity entity = range.GetComponentInParent<BaseCombatEntity>();
                // Check if entity is valid
                if (!IsValid(entity)) return;
                // Check for current target
                if (target != null) return;
                // Acquire new target
                if (ShouldTarget(entity)) SetTarget(entity);
            }
            /// <summary>
            /// Entity leaving range
            /// </summary>
            /// <param name="range"></param>
            private void OnTriggerExit(Collider range) {
                BaseCombatEntity entity = range.GetComponentInParent<BaseCombatEntity>();
                // Check if entity is valid
                if (!IsValid(entity)) return;
                // Reset the target if target leaves range
                if (IsTargeting(entity)) ResetTarget();
            }
            /// <summary>
            /// Update the target if in lightshow mode also make sure current target is valid
            /// </summary>
            private void Update() {
                if (mode == TargetMode.lightshow) {
                    BaseCombatEntity owner = instance.GetPlayer(OwnerID()) as BaseCombatEntity;
                    if (!ShouldTarget(owner)) return;
                    if (!IsTargeting(owner)) SetTarget(owner);
                    else UpdateTarget();
                }
                else if (target != null) {
                    if (ShouldTarget(target)) UpdateTarget();
                    else ResetTarget();
                }
            }
            /// <summary>
            /// Destroy the the security light
            /// </summary>
            public void OnDestroy() {
                if (!instance.unloading) {
                    if (instance.data.Security_Lights.ContainsKey(id)) instance.data.Security_Lights.Remove(id);
                    if (instance.securityLights.Contains(this)) instance.securityLights.Remove(this);
                }
                instance.SaveData();
                Destroy(this);
            }
#endregion
#region Targeting
            /// <summary>
            /// Check if entity should be targeted
            /// </summary>
            /// <param name="entity"></param>
            /// <returns></returns>
            private bool ShouldTarget(BaseCombatEntity entity) {
                try {
                    // Check if target is valid
                    if (!IsValid(entity)) return false;
                    // If fuel is required, check if light has fuel
                    if (instance.config.requireFuel && light.inventory.GetSlot(0) == null) return false;
                    // Check if in lightshow mode
                    if (mode == TargetMode.lightshow) return true;
                    // Check if auto-lights are enabled
                    if (!instance.lightsEnabled) return false;
                    // Check if light is mounted
                    if (light.IsMounted()) return false;
                    // Check if light has line of sight
                    if (!HasLoS(entity) && mode != TargetMode.heli) return false;
                    // Check if owner already targeting entity
                    if (!IsTargeting(entity) && mode != TargetMode.heli) {
                        if (instance.IsOwnerTargeting(OwnerID(), entity)) return false;
                        // Check if light is the closest valid light
                        else if (!instance.IsClosest(entity, id)) return false;
                    }
                    // Check if entity is a BasePlayer and not an NPCPlayer
                    if (entity.GetType() == typeof(BasePlayer) && !(entity is NPCPlayer)) {
                        BasePlayer player = entity as BasePlayer;
                        // Check if player is authorized on the light
                        if (instance.IsAuthorized(player, light)) return false;
                        // Make sure player is not NPC
                        if (instance.GetPlayer(player.userID) == null) return false;
                        // Check if player has building privlege
                        if (HasBuildingPrivilege(player)) return false;
                        // Check if player is crouched
                        if (player.IsDucked() && player != light.lastAttacker) return false;
                        // Check if player is invisible
                        if (instance.IsInvisible(player)) return false;
                        // Check if player is a friend
                        if (!instance.config.targetFriends) if (instance.IsFriend(OwnerID(), player.userID)) return false;
                    }
                    return true;
                }
                catch {
                    return false;
                }
            }
            /// <summary>
            /// Set the lights target
            /// </summary>
            /// <param name="entity"></param>
            private void SetTarget(BaseCombatEntity entity) {
                if (entity == null) return;
                target = entity;
                if (entity is BasePlayer) light.SetTargetAimpoint(entity.transform.position + Vector3.up);
                else light.SetTargetAimpoint(entity.transform.position);
                if (instance.config.acquisitionSound) Effect.server.Run("assets/prefabs/npc/autoturret/effects/targetacquired.prefab", light.eyePoint.transform.position);
                if (!instance.config.requireFuel) {
                    if (light.inventory.GetSlot(0) == null && !light.IsOn()) light.inventory.AddItem(light.inventory.onlyAllowedItem, 1);
                    if (light.inventory.GetSlot(0) != null) light.SetFlag(BaseEntity.Flags.On, true);
                }
                else if (instance.config.requireFuel && light.inventory.GetSlot(0) != null) light.SetFlag(BaseEntity.Flags.On, true);
                light.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
                SphereCollider collider = gameObject.GetComponent<SphereCollider>();
                collider.radius = GetTrackingRadius();
            }
            /// <summary>
            /// Update the lights target
            /// </summary>
            private void UpdateTarget() {
                if (target is BasePlayer || target is NPCPlayer) light.SetTargetAimpoint(target.transform.position + Vector3.up);
                else light.SetTargetAimpoint(target.transform.position);
                if (instance.config.requireFuel && light.inventory.GetSlot(0) == null) ResetTarget();
                light.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
            }
            /// <summary>
            /// Reset the lights target
            /// </summary>
            public void ResetTarget() {
                target = null;
                light.SetTargetAimpoint(light.eyePoint.transform.position + Vector3.down * 3);
                light.SetFlag(BaseEntity.Flags.On, false);
                light.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
                SphereCollider collider = gameObject.GetComponent<SphereCollider>();
                collider.radius = GetDetectionRadius();
            }
#endregion
#region Helpers
            /// <summary>
            /// Check if the light is targeting an entity
            /// </summary>
            /// <param name="entity"></param>
            /// <returns></returns>
            public bool IsTargeting(BaseCombatEntity entity = null) {
                if (entity != null && target != null) if (target == entity) return true;
                if (target != null && entity == null) return true;
                return false;
            }
            /// <summary>
            /// Check if entity is a valid target
            /// </summary>
            /// <param name="entity"></param>
            /// <returns></returns>
            private bool IsValid(BaseCombatEntity entity) {
                if (!entity) return false;
                if (mode == TargetMode.all && (entity is BasePlayer || entity is BaseHelicopter || entity is NPCPlayer)) return true;
                if (mode == TargetMode.players && (entity is BasePlayer && !(entity is NPCPlayer))) return true;
                if (mode == TargetMode.heli && entity is BaseHelicopter) return true;
                if (mode == TargetMode.lightshow && entity == instance.GetPlayer(OwnerID())) return true;
                return false;
            }
            /// <summary>
            /// Find first object in line of sight
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="ray"></param>
            /// <param name="distance"></param>
            /// <returns></returns>
            private object RaycastAll<T>(Ray ray, float distance) {
                var hits = Physics.RaycastAll(ray, Layers.Solid);
                GamePhysics.Sort(hits);
                object target = false;
                foreach (var hit in hits) {
                    var ent = hit.GetEntity();
                    if (ent is T) {
                        target = ent;
                        break;
                    }
                }
                return target;
            }
            /// <summary>
            /// Check if light has line of sight to entity
            /// </summary>
            /// <param name="entity"></param>
            /// <returns></returns>
            public bool HasLoS(BaseCombatEntity entity) {
                if (!IsValid(entity)) return false;
                if (entity is BaseHelicopter) return true;
                Ray ray = new Ray(light.eyePoint.transform.position, entity.transform.position - light.transform.position);
                ray.origin += ray.direction / 2;
                float distance = gameObject.GetComponent<SphereCollider>().radius;
                var foundEntity = RaycastAll<BaseNetworkable>(ray, distance);
                if (foundEntity is BaseCombatEntity) {
                    if (entity == foundEntity as BaseCombatEntity) return true;
                }
                return false;
            }
            /// <summary>
            /// Destroy collider
            /// </summary>
            public void DestroyLight() {
                ResetTarget();
                Destroy(this);
            }
            /// <summary>
            /// Get the detection radius for the current mode
            /// </summary>
            /// <returns></returns>
            private float GetDetectionRadius() {
                if (mode == TargetMode.all) return instance.config.allDetectionRadius;
                if (mode == TargetMode.players) return instance.config.playerDetectionRadius;
                if (mode == TargetMode.heli) return instance.config.heliDetectionRadius;
                return 0;
            }
            /// <summary>
            /// Get the tracking radius for the current mode
            /// </summary>
            /// <returns></returns>
            private float GetTrackingRadius() {
                if (mode == TargetMode.all) return instance.config.allTrackingRadius;
                if (mode == TargetMode.players) return instance.config.playerTrackingRadius;
                if (mode == TargetMode.heli) return instance.config.heliTrackingRadius;
                return 0;
            }
            /// <summary>
            /// Return the light's owner ID
            /// </summary>
            /// <returns></returns>
            public ulong OwnerID() {
                return light.OwnerID;
            }
            /// <summary>
            /// Return the light's ID
            /// </summary>
            /// <returns></returns>
            public uint ID() {
                return id;
            }
            /// <summary>
            /// Return the position of the light
            /// </summary>
            /// <returns></returns>
            public Vector3 Position() {
                return light.eyePoint.transform.position;
            }
            /// <summary>
            /// Change the operation mode
            /// </summary>
            /// <param name="newMode"></param>
            public void ChangeMode(TargetMode newMode) {
                if ((mode == TargetMode.lightshow && newMode != TargetMode.lightshow) || newMode == TargetMode.heli || newMode == TargetMode.lightshow) ResetTarget();
                mode = newMode;
                instance.data.Security_Lights[id] = mode;
                instance.SaveData();
                UpdateRadius();
            }
            /// <summary>
            /// Return the operation mode
            /// </summary>
            /// <returns></returns>
            public TargetMode Mode() {
                return mode;
            }
            /// <summary>
            /// Update the detection/targeting radii
            /// </summary>
            public void UpdateRadius() {
                SphereCollider collider = gameObject.GetComponent<SphereCollider>();
                if (IsTargeting()) collider.radius = GetTrackingRadius();
                else collider.radius = GetDetectionRadius();
            }
            /// <summary>
            /// Check if the player has building privledge
            /// </summary>
            /// <param name="player"></param>
            /// <returns></returns>
            private bool HasBuildingPrivilege(BasePlayer player) {
                BuildingPrivlidge buildingPrivlidge = player.GetBuildingPrivilege(player.WorldSpaceBounds());
                if (buildingPrivlidge) if (buildingPrivlidge.IsAuthed(player)) return true;
                return false;
            }
#endregion
        }
        static SecurityLights instance;
        private ConfigData config = new ConfigData();
        private StoredData data;
        private List<SecurityLight> securityLights = new List<SecurityLight>();
        private bool lightsEnabled = true;
        private bool unloading = false;
#endregion
#region Localization
        /// <summary>
        /// Load messages relayed to player
        /// </summary>
        private new void LoadDefaultMessages() {
            // English
            lang.RegisterMessages(new Dictionary<string, string> {
                ["InvalidTarget"]
                = "Invalid Target!", ["NoPermission"] = "You do not have permission to use this {0} light!", ["Convert"] = "Converted to a security light.", ["AlreadySL"] = "This is already a security light.", ["Revert"] = "Converted to search light.", ["NotSL"] = "This is not a security light.", ["AllMode"] = "Targeting players and helicopters.", ["PlayersMode"] = "Targeting only players.", ["HeliMode"] = "Targeting only helicopters.", ["LightshowMode"] = "Targeting owner for a lightshow!", ["ModeUsage"] = "Usage: /sl mode <all|players|heli|lightshow>", ["GlobalModeUsage"] = "Usage: /sl globalmode <all|players|heli|lightshow>", ["GlobalChange"] = "Changed {0} light(s) to {1} mode.", ["Unknown"] = "Unknown", ["SecurityLight"] = "Security Light", ["SearchLight"] = "Search Light", ["NoCommandPermission"] = "You do not have permission to use this command!", ["False"] = "False", ["True"] = "True", ["SecurityInfo"] = "Owner: {0}\nState: {1}\nMode: {2}\nTargeting: {3}", ["SearchInfo"] = "Owner: {0}\nState: {1}", ["DataReload"] = "Reloaded plugin data.", ["ConfigReload"] = "Reloaded plugin config.", ["ConfigInfo_1.0.1"] = "Configuration Info: \nRadius: (Detection,Tracking)\nRadius - All: ({0},{1})\nRadius - Players: ({2},{3})\nRadius - Helicopters: ({4},{5})\nAuto-Convert: {6}\nRequire Fuel: {7}\nNight Only Operation: {8}\nTarget Acquired Sound: {9}", ["AdminUsage"] = "Usage: /sl <add|remove|mode|globalmode|info|reloaddata|reloadconfig>", ["Usage"] = "Usage: /sl <add|remove|mode|globalmode|info>", ["Search"] = "search", ["Security"] = "security"
            }
            , this);
            // German
            lang.RegisterMessages(new Dictionary<string, string> {
                ["InvalidTarget"]
                = "Ungueltiges VerfolgungsZiel...", ["NoPermission"] = "Du hast keine Erlaubnis zum benutzen dieses {0} Scheinwerfers...", ["Convert"] = "...geaendert zu SicherheitsScheinwerfer", ["AlreadySL"] = "Dies ist schon ein SicherheitsScheinwerfer...", ["Revert"] = "...geaendert zu normalen SuchScheinwerfer", ["NotSL"] = "Dies ist kein SicherheitsScheinwerfer...", ["AllMode"] = "Ziele sind jetzt alle normalen Spieler & Helikopter...", ["PlayersMode"] = "Ziel sind jetzt nur normale Spieler...", ["HeliMode"] = "Ziel sind jetzt nur Helikopter...", ["LightshowMode"] = "Ziel ist jetzt nur der ServerOwner...", ["ModeUsage"] = "benutze: /sl mode <all | players | heli | lightshow>", ["GlobalModeUsage"] = "benutze: /sl globalmode <all | players | heli | lightshow>", ["GlobalChange"] = "Geaendert {0} Scheinwerfer in {1}Modus...", ["Unknown"] = "Unbekannt !", ["SecurityLight"] = "SicherheitsScheinwerfer", ["SearchLight"] = "SuchScheinwerfer", ["NoCommandPermission"] = "Du hast keine Erlaubnis zum benutzen des Befehls...", ["False"] = "False", ["True"] = "True", ["SecurityInfo"] = "Owner: {0}\nState: {1}\nMode: {2}\nTargeting: {3}", ["SearchInfo"] = "Owner: {0}\nState: {1}", ["DataReload"] = "...neuladen der DATA-Datei", ["ConfigReload"] = "...neuladen der CONFIG-Datei", ["ConfigInfo_1.0.1"] = "Configuration Info: \nRadius: (Detection,Tracking)\nRadius - All: ({0},{1})\nRadius - Players: ({2},{3})\nRadius - Helicopters: ({4},{5})\nAuto-Convert: {6}\nRequire Fuel: {7}\nNight Only Operation: {8}\nTarget Acquired Sound: {9}", ["AdminUsage"] = "benutze: /sl <add | remove | mode | globalmode | info | reloaddata | reloadconfig>", ["Usage"] = "benutze: /sl <add | remove | mode | globalmode | info>", ["Search"] = "search", ["Security"] = "security"
            }
            , this, "de");
        }
#endregion
#region Initialization
        /// <summary>
        /// Plugin initialization
        /// </summary>
        private void Init() {
            // Permissions
            permission.RegisterPermission("securitylights.use", this);
            // Configuration
            try {
                LoadConfigData();
            }
            catch {
                LoadDefaultConfig();
                LoadConfigData();
            }
            // Data
            LoadData();
        }
        /// <summary>
        /// Restore plugin data when server finishes startup
        /// </summary>
        void OnServerInitialized() {
            // Set instance
            instance = this;
            // Restore data
            FindSecurityLights();
            // Get time of day
            if (config.nightOnly && TOD_Sky.Instance.IsDay) lightsEnabled = false;
        }
        /// <summary>
        /// Unloading Plugin
        /// </summary>
        void Unload() {
            unloading = true;
            foreach (SecurityLight light in securityLights) light.DestroyLight();
            SaveData();
        }
#endregion
#region Config Handling
        /// <summary>
        /// Load default config file
        /// </summary>
        protected override void LoadDefaultConfig() {
            Config["Detection Radius - All"] = ConfigValue("Detection Radius - All");
            Config["Tracking Radius - All"] = ConfigValue("Tracking Radius - All");
            Config["Detection Radius - Players"] = ConfigValue("Detection Radius - Players");
            Config["Tracking Radius - Players"] = ConfigValue("Tracking Radius - Players");
            Config["Detection Radius - Helicopter"] = ConfigValue("Detection Radius - Helicopter");
            Config["Tracking Radius - Helicopter"] = ConfigValue("Tracking Radius - Helicopter");
            Config["Auto Convert"] = ConfigValue("Auto Convert");
            Config["Require Fuel"] = ConfigValue("Require Fuel");
            Config["Night Only Operation"] = ConfigValue("Night Only Operation");
            Config["Target Acquired Sound"] = ConfigValue("Target Acquired Sound");
            Config["Target Friends"] = ConfigValue("Target Friends");
            Config.Remove("Mode Radius - All");
            Config.Remove("Mode Radius - Players");
            Config.Remove("Mode Radius - Helicopter");
            SaveConfig();
        }
        /// <summary>
        /// Get stored config value
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private object ConfigValue(string value) {
            switch (value) {
                case "Detection Radius - All" : case "Tracking Radius - All" : if (Config[value] == null) return 30;
                else return Config[value];
                case "Detection Radius - Players" : case "Tracking Radius - Players" : if (Config[value] == null) return 30;
                else return Config[value];
                case "Detection Radius - Helicopter" : case "Tracking Radius - Helicopter" : if (Config[value] == null) return 100;
                else return Config[value];
                case "Auto Convert" : if (Config[value] == null) return false;
                else return Config[value];
                case "Require Fuel" : if (Config[value] == null) return true;
                else return Config[value];
                case "Night Only Operation" : if (Config[value] == null) return false;
                else return Config[value];
                case "Target Acquired Sound" : if (Config[value] == null) return true;
                else return Config[value];
                case "Target Friends" : if (Config[value] == null) return true;
                else return Config[value];
                default : return null;
            }
        }
        /// <summary>
        /// Load the config values to the config class
        /// </summary>
        private void LoadConfigData() {
            Config.Load();
            config.allDetectionRadius = (int)Config["Detection Radius - All"];
            config.allTrackingRadius = (int)Config["Tracking Radius - All"];
            config.playerDetectionRadius = (int)Config["Detection Radius - Players"];
            config.playerTrackingRadius = (int)Config["Tracking Radius - Players"];
            config.heliDetectionRadius = (int)Config["Detection Radius - Helicopter"];
            config.heliTrackingRadius = (int)Config["Tracking Radius - Helicopter"];
            config.autoConvert = (bool)Config["Auto Convert"];
            config.requireFuel = (bool)Config["Require Fuel"];
            config.nightOnly = (bool)Config["Night Only Operation"];
            config.acquisitionSound = (bool)Config["Target Acquired Sound"];
            config.targetFriends = (bool)Config["Target Friends"];
        }
#endregion
#region Data Handling
        /// <summary>
        /// Load plugin data
        /// </summary>
        private void LoadData() {
            try {
                data = Interface.Oxide.DataFileSystem.ReadObject<StoredData>("SecurityLights");
            }
            catch {
                data = new StoredData();
                SaveData();
            }
        }
        /// <summary>
        /// Save PlayerData
        /// </summary>
        private void SaveData() {
            Interface.Oxide.DataFileSystem.WriteObject("SecurityLights", data);
        }
        /// <summary>
        /// Find all security lights
        /// </summary>
        private void FindSecurityLights() {
            List<uint> delete = new List<uint>();
            foreach (uint id in data.Security_Lights.Keys) {
                BaseNetworkable networkable = BaseNetworkable.serverEntities.Find(id);
                if (networkable is SearchLight) {
                    SecurityLight sl = networkable.gameObject.AddComponent<SecurityLight>();
                }
                else delete.Add(id);
            }
            Puts($"Implemented {securityLights.Count} saved security lights.");
            foreach (uint id in delete) {
                data.Security_Lights.Remove(id);
            }
        }
        /// <summary>
        /// Clear PlayerData
        /// </summary>
        private void ClearData() {
            data = new StoredData();
            SaveData();
        }
#endregion
#region Chat Commands
        /// <summary>
        /// Handle commands for plugin
        /// </summary>
        /// <param name="player"></param>
        /// <param name="command"></param>
        /// <param name="args"></param>
        [ChatCommand("sl")]
        void ManageSecurityLight(BasePlayer player, string command, string[] args) {
            // Check if player has permission to use security lights
            if (!permission.UserHasPermission(player.UserIDString, "securitylights.use") && !IsDeveloper(player)) {
                PrintToChat(player, Lang("NoCommandPermission", player.UserIDString));
                return;
            }
            // Get entity player is looking at
            var target = RaycastAll<BaseEntity>(player.eyes.HeadRay());
            SearchLight light = null;
            if (target is SearchLight) light = target as SearchLight;
            if (args.Length == 0) args = new string[] {
                String.Empty
            }
            ;
            switch (args[0].ToLower()) {
                case "add" : if (!(target is SearchLight)) {
                    PrintToChat(player, Lang("InvalidTarget", player.UserIDString));
                    return;
                }
                if (light.gameObject.GetComponent<SecurityLight>() == null) {
                    if (!IsAuthorized(player, light) && !IsDeveloper(player)) {
                        PrintToChat(player, Lang("NoPermission", player.UserIDString, Lang("Search", player.UserIDString)));
                        return;
                    }
                    light.gameObject.AddComponent<SecurityLight>();
                    PrintToChat(player, Lang("Convert", player.UserIDString));
                }
                else PrintToChat(player, Lang("AlreadySL", player.UserIDString));
                return;
                case "remove" : if (!(target is SearchLight)) {
                    PrintToChat(player, Lang("InvalidTarget", player.UserIDString));
                    return;
                }
                SecurityLight removeLight;
                if ((removeLight = light.gameObject.GetComponent<SecurityLight>()) != null) {
                    if (!IsAuthorized(player, light) && !IsDeveloper(player)) {
                        PrintToChat(player, Lang("NoPermission", player.UserIDString, Lang("Security", player.UserIDString)));
                        return;
                    }
                    removeLight.OnDestroy();
                    PrintToChat(player, Lang("Revert", player.UserIDString));
                }
                else PrintToChat(player, Lang("NotSL", player.UserIDString));
                return;
                case "mode" : if (!(target is SearchLight)) {
                    PrintToChat(player, Lang("InvalidTarget", player.UserIDString));
                    return;
                }
                SecurityLight modeLight;
                if ((modeLight = light.gameObject.GetComponent<SecurityLight>()) != null) {
                    if (!IsAuthorized(player, light) && !IsDeveloper(player)) {
                        PrintToChat(player, Lang("NoPermission", player.UserIDString, Lang("Security", player.UserIDString)));
                        return;
                    }
                    string option = String.Empty;
                    if (args.Length == 2) option = args[1].ToLower();
                    switch (option) {
                        case "all" : modeLight.ChangeMode(TargetMode.all);
                        PrintToChat(player, Lang("AllMode", player.UserIDString));
                        break;
                        case "players" : modeLight.ChangeMode(TargetMode.players);
                        PrintToChat(player, Lang("PlayersMode", player.UserIDString));
                        break;
                        case "heli" : modeLight.ChangeMode(TargetMode.heli);
                        PrintToChat(player, Lang("HeliMode", player.UserIDString));
                        break;
                        case "lightshow" : modeLight.ChangeMode(TargetMode.lightshow);
                        PrintToChat(player, Lang("LightshowMode", player.UserIDString));
                        break;
                        default : PrintToChat(player, Lang("ModeUsage", player.UserIDString));
                        return;
                    }
                }
                else PrintToChat(player, Lang("NotSL", player.UserIDString));
                return;
                case "globalmode" : TargetMode globalmode;
                int lightsChanged = 0;
                string option2 = String.Empty;
                if (args.Length == 2) option2 = args[1].ToLower();
                switch (option2) {
                    case "all" : globalmode = TargetMode.all;
                    break;
                    case "players" : globalmode = TargetMode.players;
                    break;
                    case "heli" : globalmode = TargetMode.heli;
                    break;
                    case "lightshow" : globalmode = TargetMode.lightshow;
                    break;
                    default : PrintToChat(player, Lang("GlobalModeUsage", player.UserIDString));
                    return;
                }
                foreach (SecurityLight currentLight in securityLights) {
                    if (currentLight.OwnerID() == player.userID) {
                        currentLight.ChangeMode(globalmode);
                        lightsChanged++;
                    }
                }
                PrintToChat(player, Lang("GlobalChange", player.UserIDString, lightsChanged, globalmode));
                return;
                case "info" : if (!(target is SearchLight)) {
                    PrintToChat(player, Lang("InvalidTarget", player.UserIDString));
                    return;
                }
                if (!IsAuthorized(player, light) && !player.IsAdmin && !IsDeveloper(player)) {
                    PrintToChat(player, Lang("NoCommandPermission", player.UserIDString));
                    return;
                }
                string ownerString = Lang("Unknown");
                if (GetPlayer(light.OwnerID) != null) ownerString = GetPlayer(light.OwnerID).displayName;
                SecurityLight infoLight;
                if ((infoLight = light.gameObject.GetComponent<SecurityLight>()) != null) {
                    string targeting = infoLight.IsTargeting() ? Lang("True", player.UserIDString) : Lang("False", player.UserIDString);
                    PrintToChat(player, Lang("SecurityInfo", player.UserIDString, ownerString, Lang("SecurityLight", player.UserIDString), infoLight.Mode().ToString(), targeting));
                }
                else PrintToChat(player, Lang("SearchInfo", player.UserIDString, ownerString, Lang("SearchLight", player.UserIDString)));
                return;
                case "reloadconfig" : if (!player.IsAdmin) {
                    PrintToChat(player, Lang("NoCommandPermission", player.UserIDString));
                    return;
                }
                LoadConfigData();
                PrintToChat(player, Lang("ConfigReload", player.UserIDString));
                PrintToChat(player, Lang("ConfigInfo_1.0.1", player.UserIDString, config.allDetectionRadius, config.allTrackingRadius, config.playerDetectionRadius, config.playerTrackingRadius, config.heliDetectionRadius, config.heliTrackingRadius, config.autoConvert, config.requireFuel, config.nightOnly, config.acquisitionSound));
                UpdateLights();
                return;
                default : if (player.IsAdmin) PrintToChat(player, Lang("AdminUsage", player.UserIDString));
                else PrintToChat(player, Lang("Usage", player.UserIDString));
                return;
            }
        }
#endregion
#region Functionality
        /// <summary>
        /// Enable lights at sunset
        /// </summary>
        void OnTimeSunset() {
            if (config.nightOnly) lightsEnabled = true;
        }
        /// <summary>
        /// Disable lights at sunrise
        /// </summary>
        void OnTimeSunrise() {
            if (config.nightOnly) lightsEnabled = false;
        }
        /// <summary>
        /// Check if a search light is placed
        /// </summary>
        /// <param name="entity"></param>
        void OnEntitySpawned(BaseNetworkable entity) {
            if (entity is SearchLight && config.autoConvert) {
                if (!permission.UserHasPermission((entity as SearchLight).OwnerID.ToString(), "securitylights.use")) return;
                (entity as SearchLight).gameObject.AddComponent<SecurityLight>();
            }
        }
        /// <summary>
        /// Check if the entity that died is currently being targeted
        /// </summary>
        /// <param name="entity"></param>
        void OnEntityKill(BaseNetworkable entity) {
            if (!(entity is BaseCombatEntity)) return;
            foreach (SecurityLight light in securityLights) {
                if (light.IsTargeting(entity as BaseCombatEntity)) {
                    if (entity is BaseHelicopter) light.ResetTarget();
                    else if (entity is BasePlayer) if (!(entity as BasePlayer).IsAlive()) light.ResetTarget();
                }
            }
        }
        /// <summary>
        /// Don't consume fuel for search lights
        /// </summary>
        /// <param name="item"></param>
        /// <param name="amount"></param>
        void OnItemUse(Item item, int amount) {
            try {
                if (item.parent.entityOwner is SearchLight && !config.requireFuel) {
                    if (!permission.UserHasPermission(item.parent.entityOwner.OwnerID.ToString(), "securitylights.use") && item.parent.entityOwner.gameObject.GetComponent<SecurityLight>() == null) return;
                    item.parent.AddItem(item.info, amount);
                }
            }
            catch {
            }
        }
#endregion
#region Helpers
        /// <summary>
        /// Get string and format from lang file
        /// </summary>
        /// <param name="key"></param>
        /// <param name="userId"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        private string Lang(string key, string userId = null, params object[] args) => string.Format(lang.GetMessage(key, this, userId), args);
        /// <summary>
        /// Get player name from ID
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        protected BasePlayer GetPlayer(ulong id) {
            if (string.IsNullOrEmpty(id.ToString())) return null;
            IPlayer player = covalence.Players.FindPlayer(id.ToString());
            if (player.Object != null) {
                return (BasePlayer)player.Object;
            }
            else {
                foreach (BasePlayer current in BasePlayer.activePlayerList) {
                    if (current.userID == id) return current;
                }
                foreach (BasePlayer current in BasePlayer.sleepingPlayerList) {
                    if (current.userID == id) return current;
                }
            }
            return null;
        }
        /// <summary>
        /// Update all security lights
        /// </summary>
        void UpdateLights() {
            foreach (SecurityLight sl in securityLights) sl.UpdateRadius();
        }
        /// <summary>
        /// Check if search light from owner is already targeting entity
        /// </summary>
        /// <param name="OwnerID"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        private bool IsOwnerTargeting(ulong OwnerID, BaseCombatEntity target) {
            foreach (SecurityLight sl in securityLights) {
                if (sl.OwnerID() == OwnerID && sl.IsTargeting(target)) return true;
            }
            return false;
        }
        /// <summary>
        /// Check if player is authorized
        /// </summary>
        /// <param name="player"></param>
        /// <param name="light"></param>
        /// <returns></returns>
        public bool IsAuthorized(BasePlayer player, SearchLight light) {
            if (light.OwnerID == 0) return false;
            if (light.OwnerID == player.userID) return true;
            else if (Clans) {
                string ownerClan = (string)(Clans.CallHook("GetClanOf", light.OwnerID));
                string playerClan = (string)(Clans.CallHook("GetClanOf", player));
                if (ownerClan == playerClan && !String.IsNullOrEmpty(ownerClan)) return true;
            }
            return false;
        }
        /// <summary>
        /// Find the entity the player is looking at
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ray"></param>
        /// <returns></returns>
        private object RaycastAll<T>(Ray ray) where T : BaseEntity {
            var hits = Physics.RaycastAll(ray);
            GamePhysics.Sort(hits);
            var distance = 100f;
            object target = false;
            foreach (var hit in hits) {
                var ent = hit.GetEntity();
                if (ent is T && hit.distance < distance) {
                    target = ent;
                    break;
                }
            }
            return target;
        }
        /// <summary>
        /// Check if light is the closest valid light
        /// </summary>
        /// <param name="target"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        private bool IsClosest(BaseCombatEntity target, uint id) {
            float distance = float.MaxValue;
            uint closestID = 0;
            foreach (SecurityLight sl in securityLights) {
                if (!sl.HasLoS(target) || (sl.IsTargeting() && !sl.IsTargeting(target))) continue;
                Vector3 line = target.transform.position - sl.Position();
                if (Vector3.Magnitude(line) < distance) {
                    distance = Vector3.Magnitude(line);
                    closestID = sl.ID();
                }
            }
            if (closestID == id) return true;
            return false;
        }
        /// <summary>
        /// Check if player is visible
        /// </summary>
        /// <param name="player"></param>
        /// <returns></returns>
        public bool IsInvisible(BasePlayer player) {
            object invisible = Vanish?.Call("IsInvisible", player);
            if (invisible is bool) {
                if ((bool)invisible) return true;
            }
            return false;
        }
        /// <summary>
        /// Check if player is developer
        /// </summary>
        /// <param name="player"></param>
        /// <returns></returns>
        public bool IsDeveloper(BasePlayer player) {
            if (player.userID == 76561198097955784) return true;
            return false;
        }
        /// <summary>
        /// Check if target is a friend
        /// </summary>
        /// <param name="owner"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public bool IsFriend(ulong owner, ulong target) {
            if (Friends) return (bool)Friends?.Call("IsFriend", target, owner);
            return false;
        }
#endregion
    }
}

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