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

FREE RecoilViewer : 1.4.1 1.4.1

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Core.Configuration;
using Oxide.Core.Libraries.Covalence;
using Oxide.Game.Rust.Libraries;
using Oxide.Game.Rust.Cui;
using Rust;
using Network;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using ProtoBuf;
// https://modhub.to
// This is a user submitted Rust Plugin checked and verified by ModHub
// ModHub is the largest Server Owner Trading Platform Online
namespace Oxide.Plugins {
    [Info("RecoilViewer", "ModHub.to", "1.4.1")]
    [Description("Displays the players recoil on the screen.")]
    public class RecoilViewer : RustPlugin {
#region Fields
        [PluginReference]
        Plugin ImageLibrary;
        private static RecoilViewer plugin;
        private Dictionary <string, List <Vector2>> patternData;
        private BasePlayer ultArkan;
        List<ulong> AutoArkan = new List<ulong>();
        List<ulong> NoSpectate = new List<ulong>();
        private Dictionary<BasePlayer, ShooterData> CacheInfo = new Dictionary<BasePlayer, ShooterData>();
        private static Dictionary<string, Vector2> Sensibility = new Dictionary<string, Vector2>() {
            {
                "rifle.ak", new Vector2(11, 14)
            }
            , {
                "rifle.ak.ice", new Vector2(11, 14)
            }
            , {
                "rifle.lr300", new Vector2(27, 30)
            }
            , {
                "smg.mp5", new Vector2(27, 30)
            }
            , {
                "smg.thompson", new Vector2(27, 30)
            }
            , {
                "smg.2", new Vector2(27, 30)
            }
            , {
                "lmg.m249", new Vector2(27, 30)
            }
        }
        ;
        private const string UI_player_shot = "player_shot.GUI";
        private const string UI_player_hits = "player_hits.GUI";
        private const string UI_weapon_pattern = "weapon_pattern.GUI";
        private const string UI_panel_show = "panel_show.GUI";
#endregion
#region Oxide Hooks
        private void OnServerInitialized() {
            if (!ImageLibrary) {
                PrintWarning("Image Library not detected, unloading RecoilViewer");
                Interface.Oxide.UnloadPlugin(Name);
                return;
            }
            permission.RegisterPermission("RecoilViewer.player", this);
            permission.RegisterPermission("RecoilViewer.admin", this);
            permission.RegisterPermission("RecoilViewer.spectate", this);
            permission.RegisterPermission("RecoilViewer.training", this);
            permission.RegisterPermission("RecoilViewer.zonemanager", this);
            permission.RegisterPermission("RecoilViewer.autoarkan", this);
            ReadData();
            AddImageLibrary(config.info.shots.iconURL, config.info.shots.iconURL);
            AddImageLibrary(config.info.hit.iconURL, config.info.hit.iconURL);
            AddImageLibrary(config.info.headshot.iconURL, config.info.headshot.iconURL);
        }
        private void Unload() {
            foreach (var player in BasePlayer.activePlayerList) {
                CloseAllGUI(player);
            }
        }
        object CanSpectateTarget(BasePlayer player, string filter) {
            if (permission.UserHasPermission(player.UserIDString, "RecoilViewer.spectate") && config.spectate && !NoSpectate.Contains(player.userID)) {
                DeleteActiveShooter(player);
                timer.Once(0.5f, () => {
                    if (player.IsSpectating()) {
                        var parentEntity = player.GetParentEntity();
                        if (parentEntity as BasePlayer != null) {
                            var PlayerActive = parentEntity as BasePlayer;
                            SpectateRecoil(player, PlayerActive);
                        }
                    }
                }
                );
            }
            return null;
        }
        object OnReloadWeapon(BasePlayer player, BaseProjectile projectile) {
            if (player == null) {
                return null;
            }
            if (!CacheInfo.ContainsKey(player) || !config.reloadClear) {
                return null;
            }
            if (CacheInfo.ContainsKey(player)) {
                ClearCacheInfo(player);
                var item = player.GetActiveItem();
                foreach (BasePlayer Viewer in CacheInfo[player].Viewers) {
                    RecoilShotsGUI(Viewer, player);
                    ShowPatternGUI(Viewer, item, -1);
                    InfoHitsGUI(Viewer, player);
                }
                return null;
            }
            return null;
        }
        private void OnPlayerAttack(BasePlayer attacker, HitInfo hitinfo) {
            if (!config.showinfo) return;
            if (hitinfo == null) return;
            if (!CacheInfo.ContainsKey(attacker)) {
                return;
            }
            SendHit(attacker, hitinfo);
        }
        private void OnWeaponFired(BaseProjectile projectile, BasePlayer player) {
            if (player == null) {
                return;
            }
            if (!CacheInfo.ContainsKey(player)) {
                return;
            }
            var item = player.GetActiveItem();
            var Weapon = item.info.shortname;
            if(!patternData.ContainsKey(Weapon)) {
                return;
            }
            if (projectile.primaryMagazine.contents == 0) {
                timer.Once(1.1f, () => {
                    if (CacheInfo.ContainsKey(player)) {
                        ClearCacheInfo(player);
                    }
                }
                );
            }
            var InfoPlayer = CacheInfo[player];
            float difference = Time.time - InfoPlayer.Time;
            if (difference > 0.5 && difference < 300.5) {
                ClearCacheInfo(player);
                InfoPlayer.Time = 0;
            }
            float rotationLastx = player?.eyes?.rotation.eulerAngles.x ?? 0;
            float rotationLasty = player?.eyes?.rotation.eulerAngles.y ?? 0;
            InfoPlayer.NewShot = new Vector2(rotationLastx, rotationLasty);
            if (InfoPlayer.OldShot.x == 0 && InfoPlayer.OldShot.y == 0) {
                float x = -patternData[Weapon][0].x;
                float y = -patternData[Weapon][0].y;
                InfoPlayer.ShootDisplay = new Vector2(x, y);
                InfoPlayer.AllShootsDisplay.Add(InfoPlayer.ShootDisplay);
                InfoPlayer.OldShot = InfoPlayer.NewShot;
                InfoPlayer.Time = Time.time;
                InfoPlayer.ShotCounter++;
                foreach (BasePlayer Viewer in InfoPlayer.Viewers) {
                    RecoilShotsGUI(Viewer, player);
                    ShowPatternGUI(Viewer, item, 0);
                    InfoHitsGUI(Viewer, player);
                }
                return;
            }
            float currentX = InfoPlayer.NewShot.x - InfoPlayer.OldShot.x;
            float currentY = InfoPlayer.NewShot.y - InfoPlayer.OldShot.y;
            InfoPlayer.Displacement = new Vector2(currentX, currentY);
            if (currentX < -180) {
                InfoPlayer.Displacement.x = currentX + 360;
            }
            if (currentX > 180) {
                InfoPlayer.Displacement.x = currentX - 360;
            }
            if (currentY < -180) {
                InfoPlayer.Displacement.y = currentY + 360;
            }
            if (currentY > 180) {
                InfoPlayer.Displacement.y = currentY - 360;
            }
            if(patternData.ContainsKey(Weapon)) {
                float displayX = InfoPlayer.Displacement.x * Sensibility[Weapon].x - patternData[Weapon][InfoPlayer.ShotCounter].x;
                float displayY = InfoPlayer.Displacement.y * Sensibility[Weapon].y - patternData[Weapon][InfoPlayer.ShotCounter].y;
                InfoPlayer.ShootDisplay = new Vector2(displayX, displayY);
                InfoPlayer.AllShootsDisplay.Add(InfoPlayer.ShootDisplay);
                InfoPlayer.ShotCounter++;
                //Puts("x: " + -displayX + " y: " + displayY);
            }
            foreach (BasePlayer Viewer in InfoPlayer.Viewers) {
                RecoilShotsGUI(Viewer, player);
                ShowPatternGUI(Viewer, item, InfoPlayer.ShotCounter-1);
                InfoHitsGUI(Viewer, player);
            }
            if (Weapon.Contains("smg.thompson") && InfoPlayer.ShotCounter == 20) {
                ClearCacheInfo(player);
            }
            else if (Weapon.Contains("smg.2") && InfoPlayer.ShotCounter == 24) {
                ClearCacheInfo(player);
            }
            else if (Weapon.Contains("lmg.m249") && InfoPlayer.ShotCounter == 30) {
                ClearCacheInfo(player);
            }
            else if (InfoPlayer.ShotCounter == 30) {
                ClearCacheInfo(player);
            }
            InfoPlayer.Time = Time.time;
        }
        private void OnActiveItemChanged(BasePlayer player, Item oldItem, Item newItem) {
            if (player == null) {
                return;
            }
            if (!CacheInfo.ContainsKey(player)) {
                return;
            }
            if (newItem == null) {
                return;
            }
            ClearCacheInfo(player);
            var mameActiveItem = (newItem != null ? newItem.info.displayName.english.ToUpper() : Lang("Empty"));
            //Puts("ITEM: " + player.displayName + " Name Item: " + mameActiveItem);
            foreach (BasePlayer Viewer in CacheInfo[player].Viewers) {
                WindowsViewerGUI(Viewer, newItem, player.displayName);
                InfoHitsGUI(Viewer, player);
                RecoilShotsGUI(Viewer, player);
            }
        }
        //AimTrain Hooks
        void JoinedAimTrain(BasePlayer player) {
            if (permission.UserHasPermission(player.UserIDString, "RecoilViewer.training") && config.training) {
                SpectateRecoil(player, player);
            }
        }
        void LeftAimTrain(BasePlayer player) {
            if (permission.UserHasPermission(player.UserIDString, "RecoilViewer.training") && config.training) {
                CloseRecoil(player);
            }
        }
        //ZoneManager Hooks
        void OnEnterZone(string ZoneID, BasePlayer player) {
            if (permission.UserHasPermission(player.UserIDString, "RecoilViewer.zonemanager") && config.zonemanager && config.zoneslist.Contains(ZoneID)) {
                SpectateRecoil(player, player);
            }
        }
        void OnExitZone(string ZoneID, BasePlayer player) {
            if (permission.UserHasPermission(player.UserIDString, "RecoilViewer.zonemanager") && config.zonemanager && config.zoneslist.Contains(ZoneID)) {
                CloseRecoil(player);
            }
        }
        //Arkan Hooks
        private void API_ArkanOnNoRecoilViolation(BasePlayer player, int NRViolationsNum, string json) {
            if (config.arkan && json != null) {
                if(ultArkan != player) {
                    ultArkan = player;
                    foreach (var spectate in AutoArkan) {
                        BasePlayer spect = FindPlayerByID(spectate);
                        if(spect == null) return;
                        CloseRecoil(spect);
                        SpectateRecoil(spect, player);
                    }
                }
            }
        }
#endregion
#region Commands
        [ConsoleCommand("btnclose")]
        void ConsoleCmdBtnClose(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            var action = arg.Args?.Length > 0 ? arg.Args[0] : "null";
            if (action == "RecoilShow") {
                CloseRecoil(player);
                PrintToChat(player, Lang("Disabled"));
                return;
            }
        }
        [ConsoleCommand("recoil")]
        void ConsoleCmdRecoil(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (!permission.UserHasPermission(player.UserIDString, "RecoilViewer.admin")) {
                player.ChatMessage(Lang("WithoutPermission"));
                return;
            }
            if(arg.Args == null) {
                if (CheckViewerPlayer(player)) {
                    CloseRecoil(player);
                    PrintToChat(player, Lang("Disabled"));
                }
                else {
                    PrintToChat(player, Lang("Usage"));
                }
                return;
            }
            else {
                if(arg.Args[0] == "off") {
                    NoSpectate.Add(player.userID);
                    CloseRecoil(player);
                    PrintToChat(player, Lang("DisabledSpectate"));
                    return;
                }
                if(arg.Args[0] == "arkan" && permission.UserHasPermission(player.UserIDString, "RecoilViewer.autoarkan") && config.arkan) {
                    if(!AutoArkan.Contains(player.userID)) {
                        AutoArkan.Add(player.userID);
                        PrintToChat(player, Lang("AutoArkanON"));
                    }
                    else {
                        AutoArkan.Remove(player.userID);
                        CloseRecoil(player);
                        PrintToChat(player, Lang("AutoArkanOFF"));
                    }
                    return;
                }
                else {
                    PrintToChat(player, Lang("AutoArkanPermission"));
                    return;
                }
                var ID = 0ul;
                BasePlayer search = (ulong.TryParse(arg.Args[0], out ID)) ? FindPlayerByID(ID) : FindPlayerByPartialName(arg.Args[0]);
                if (search == null) {
                    PrintToChat(player, Lang("ErrorSearch", arg.Args[0]));
                    return;
                }
                if (!CacheInfo.ContainsKey(search)) {
                    CacheInfo.Add(search, new ShooterData());
                }
                if (!CacheInfo[search].Viewers.Contains(player)) {
                    CacheInfo[search].Viewers.Add(player);
                }
                LaunchRecoil(player, search);
            }
        }
        [ChatCommand("recoil")]
        private void RecoilCommand(BasePlayer player, string command, string[] args) {
            if (args.Length == 0) {
                if (!permission.UserHasPermission(player.UserIDString, "RecoilViewer.player")) {
                    player.ChatMessage(Lang("WithoutPermission"));
                    return;
                }
                if (CheckViewerPlayer(player)) {
                    CloseRecoil(player);
                    PrintToChat(player, Lang("Disabled"));
                }
                else {
                    if (!CacheInfo.ContainsKey(player)) {
                        CacheInfo.Add(player, new ShooterData());
                    }
                    if (!CacheInfo[player].Viewers.Contains(player)) {
                        CacheInfo[player].Viewers.Add(player);
                    }
                    LaunchRecoil(player, player);
                }
                return;
            }
            if (!permission.UserHasPermission(player.UserIDString, "RecoilViewer.admin")) {
                player.ChatMessage(Lang("WithoutPermission"));
                return;
            }
            if(args[0] == "arkan" && config.arkan) {
                if(permission.UserHasPermission(player.UserIDString, "RecoilViewer.autoarkan")) {
                    if(!AutoArkan.Contains(player.userID)) {
                        AutoArkan.Add(player.userID);
                        PrintToChat(player, Lang("AutoArkanON"));
                    }
                    else {
                        AutoArkan.Remove(player.userID);
                        CloseRecoil(player);
                        PrintToChat(player, Lang("AutoArkanOFF"));
                    }
                    return;
                }
                else {
                    PrintToChat(player, Lang("AutoArkanPermission"));
                    return;
                }
            }
            var ID = 0ul;
            BasePlayer search = (ulong.TryParse(args[0], out ID)) ? FindPlayerByID(ID) : FindPlayerByPartialName(args[0]);
            if (search == null) {
                PrintToChat(player, Lang("ErrorSearch", args[0]));
                return;
            }
            DeleteActiveShooter(player);
            if (!CacheInfo.ContainsKey(search)) {
                CacheInfo.Add(search, new ShooterData());
            }
            if (!CacheInfo[search].Viewers.Contains(player)) {
                CacheInfo[search].Viewers.Add(player);
            }
            if (NoSpectate.Contains(player.userID)) {
                NoSpectate.Remove(player.userID);
            }
            LaunchRecoil(player, search);
        }
#endregion
#region Functions
        private void SendHit(BasePlayer attacker, HitInfo hitinfo) {
            var InfoPlayer = CacheInfo[attacker];
            var npc = hitinfo.HitEntity as BaseNpc;
            if (npc != null) {
                InfoPlayer.Hit++;
                foreach (BasePlayer Viewer in InfoPlayer.Viewers) {
                    InfoHitsGUI(Viewer, attacker);
                }
                return;
            }
            var victim = hitinfo.HitEntity as BasePlayer;
            if (victim == null) return;
            if (victim == attacker) return;
            if (hitinfo.isHeadshot) {
                InfoPlayer.Head++;
                foreach (BasePlayer Viewer in InfoPlayer.Viewers) {
                    InfoHitsGUI(Viewer, attacker);
                }
                return;
            }
            InfoPlayer.Hit++;
            foreach (BasePlayer Viewer in InfoPlayer.Viewers) {
                InfoHitsGUI(Viewer, attacker);
            }
        }
        private void ClearCacheInfo(BasePlayer player) {
            var InfoPlayer = CacheInfo[player];
            InfoPlayer.OldShot = new Vector2(0, 0);
            InfoPlayer.AllShootsDisplay.Clear();
            InfoPlayer.ShotCounter = 0;
            InfoPlayer.Hit = 0;
            InfoPlayer.Head = 0;
        }
        private void SpectateRecoil(BasePlayer player, BasePlayer PlayerActive) {
            if (!CacheInfo.ContainsKey(PlayerActive)) {
                CacheInfo.Add(PlayerActive, new ShooterData());
            }
            if (!CacheInfo[PlayerActive].Viewers.Contains(player)) {
                CacheInfo[PlayerActive].Viewers.Add(player);
            }
            LaunchRecoil(player, PlayerActive);
        }
        private void LaunchRecoil(BasePlayer player, BasePlayer PlayerActive) {
            PrintToChat(player, Lang("EnableViewer", PlayerActive.IPlayer.Name));
            var item = PlayerActive.GetActiveItem();
            WindowsViewerGUI(player, item, PlayerActive.displayName);
            InfoHitsGUI(player, PlayerActive);
            RecoilShotsGUI(player, PlayerActive);
            return;
        }
        private void CloseRecoil(BasePlayer player) {
            DeleteActiveShooter(player);
            CloseAllGUI(player);
        }
        private void DeleteActiveShooter(BasePlayer player) {
            foreach (KeyValuePair<BasePlayer, ShooterData> PlayerActive in CacheInfo.ToList()) {
                //Puts("PlayerActive: " + PlayerActive.Key.displayName);
                foreach (BasePlayer viewer in PlayerActive.Value.Viewers.ToList()) {
                    //Puts("Viewer: " + viewer.displayName);
                    var InfoPlayer = CacheInfo[PlayerActive.Key];
                    if (InfoPlayer.Viewers.Contains(player)) {
                        InfoPlayer.Viewers.Remove(player);
                        if (InfoPlayer.Viewers.Count == 0) {
                            //Puts("Nobody sees it, we remove: " + PlayerActive.Key.displayName);
                            CacheInfo.Remove(PlayerActive.Key);
                        }
                        break;
                    }
                }
            }
        }
        bool CheckViewerPlayer(BasePlayer player) {
            foreach (KeyValuePair<BasePlayer, ShooterData> PlayerActive in CacheInfo.ToList()) {
                foreach (BasePlayer viewer in PlayerActive.Value.Viewers.ToList()) {
                    if (CacheInfo[PlayerActive.Key].Viewers.Contains(player)) {
                        //Puts("IF YOU ARE ALREADY WATCHING " + viewer.displayName);
                        return true;
                    }
                }
            }
            //Puts("NOT SEEING ANYONE " + player.displayName);
            return false;
        }
        private void CloseAllGUI(BasePlayer Viewer) {
            CuiHelper.DestroyUi(Viewer, UI_panel_show);
            CuiHelper.DestroyUi(Viewer, UI_player_shot);
            CuiHelper.DestroyUi(Viewer, UI_player_hits);
            CuiHelper.DestroyUi(Viewer, UI_weapon_pattern);
        }
#endregion
#region Helpers
        private BasePlayer FindPlayerByPartialName(string name, bool sleepers = false) {
            if (string.IsNullOrEmpty(name)) return null;
            BasePlayer player = null;
            try {
                for (int i = 0; i < BasePlayer.activePlayerList.Count; i++) {
                    var p = BasePlayer.activePlayerList[i];
                    if (p == null) continue;
                    var pName = p?.displayName ?? string.Empty;
                    if (string.Equals(pName, name, StringComparison.OrdinalIgnoreCase)) {
                        if (player != null) return null;
                        player = p;
                        return player;
                    }
                    if (pName.IndexOf(name, StringComparison.OrdinalIgnoreCase) >= 0) {
                        if (player != null) return null;
                        player = p;
                        return player;
                    }
                }
                if (sleepers) {
                    for (int i = 0; i < BasePlayer.sleepingPlayerList.Count; i++) {
                        var p = BasePlayer.sleepingPlayerList[i];
                        if (p == null) continue;
                        var pName = p?.displayName ?? string.Empty;
                        if (string.Equals(pName, name, StringComparison.OrdinalIgnoreCase)) {
                            if (player != null) return null;
                            player = p;
                            return player;
                        }
                        if (pName.IndexOf(name, StringComparison.OrdinalIgnoreCase) >= 0) {
                            if (player != null) return null;
                            player = p;
                            return player;
                        }
                    }
                }
            }
            catch (Exception ex) {
                PrintError(ex.ToString());
                return null;
            }
            return player;
        }
        private BasePlayer FindPlayerByID(ulong userID) {
            return BasePlayer.FindByID(userID) ?? BasePlayer.FindSleeping(userID) ?? null;
        }
        private class ShooterData {
            public List<BasePlayer> Viewers = new List<BasePlayer>();
            public Vector2 OldShot = new Vector2(0, 0);
            public Vector2 NewShot = new Vector2(0, 0);
            public Vector2 Displacement = new Vector2(0, 0);
            public Vector2 ShootDisplay = new Vector2(0, 0);
            public List<Vector2> AllShootsDisplay = new List<Vector2>();
            public int ShotCounter = 0;
            public int Hit = 0;
            public int Head = 0;
            public float Time;
        }
        private string GetImage(string name) {
            return ImageLibrary?.Call<string>("GetImage", name);
        }
        private void AddImageLibrary(string name, string url) {
            if (ImageLibrary == null || !ImageLibrary.IsLoaded) {
                timer.Once(1f, () => {
                    AddImageLibrary(name, url);
                }
                );
                return;
            }
            ImageLibrary.CallHook("AddImage", url, name, (ulong) 0);
        }
#endregion
#region GUI
        private void RecoilShotsGUI(BasePlayer Viewer, BasePlayer PlayerActive) {
            CuiElementContainer container = UI.CreateElementContainer(UI_player_shot, "0 0 0 0", "0.81 0.65", "0.992 0.86");
            foreach (Vector2 point in CacheInfo[PlayerActive].AllShootsDisplay) {
                UI.Point(ref container, UI_player_shot, config.recoil.point, config.recoil.pointsize, point, config.recoil.pointcolor, true);
            }
            if(config.showinfo) {
                UI.Label(ref container, UI_player_shot, CacheInfo[PlayerActive].ShotCounter.ToString(), config.info.shots.textsize, config.info.shots.textposAnchorMin, config.info.shots.textposAnchorMax, config.info.shots.textcolor, TextAnchor.MiddleLeft, true);
            }
            CuiHelper.DestroyUi(Viewer, UI_player_shot);
            CuiHelper.AddUi(Viewer, container);
        }
        private void InfoHitsGUI(BasePlayer Viewer, BasePlayer PlayerActive) {
            if(config.showinfo) {
                int shots = CacheInfo[PlayerActive].ShotCounter;
                int hits = CacheInfo[PlayerActive].Hit;
                int heads = CacheInfo[PlayerActive].Head;
                CuiElementContainer container = UI.CreateElementContainer(UI_player_hits, "0 0 0 0", "0.810 0.52", "0.992 0.860");
                UI.Label(ref container, UI_player_hits, hits.ToString(), config.info.hit.textsize, config.info.hit.textposAnchorMin, config.info.hit.textposAnchorMax, config.info.hit.textcolor, TextAnchor.MiddleLeft, true);
                UI.Label(ref container, UI_player_hits, heads.ToString(), config.info.headshot.textsize, config.info.headshot.textposAnchorMin, config.info.headshot.textposAnchorMax, config.info.headshot.textcolor, TextAnchor.MiddleLeft, true);
                if(config.info.accuracy.enabled) {
                    int accuracy = 0;
                    float maxProgress = 0.0f;
                    string color = "0 0 0 0";
                    if(shots > 0) {
                        accuracy = (int) Math.Round((double) (100 * (hits+heads)) / shots);
                        maxProgress = 0.01f * accuracy;
                        if(accuracy > 30) {
                            color = config.info.accuracy.bgcolor30;
                        }
                        if(accuracy > 60) {
                            color = config.info.accuracy.bgcolor60;
                        }
                        if(accuracy > 80) {
                            color = config.info.accuracy.bgcolor80;
                        }
                    }
                    UI.Panel(ref container, UI_player_hits, color, "0.0 0.008", $"{(float) maxProgress} 0.1205", false, "assets/content/ui/namefontmaterial.mat");
                    UI.Label(ref container, UI_player_hits, Lang("Accuracy", accuracy), 12, "0 0.025", "1 0.1", config.info.accuracy.textcolor, TextAnchor.MiddleCenter, true);
                }
                CuiHelper.DestroyUi(Viewer, UI_player_hits);
                CuiHelper.AddUi(Viewer, container);
            }
        }
        private void WindowsViewerGUI(BasePlayer player, Item item, string ViewerName = "") {
            var mameActiveItem = (item != null ? item.info.displayName.english.ToUpper() : Lang("Empty"));
            CuiElementContainer container = UI.CreateElementContainer(UI_panel_show, config.windows.bgcolor, config.windows.posAnchorMin, config.windows.posAnchorMax, "assets/content/ui/uibackgroundblur-ingamemenu.mat");
            UI.Button(ref container, UI_panel_show, config.windows.closebgcolor, Lang("Close"), 12, "0.80 0.89", "0.98 0.98", $"global.btnclose RecoilShow");
            UI.Label(ref container, UI_panel_show, $"{mameActiveItem}", config.text.weaponsize, config.text.weaponposAnchorMin, config.text.weaponposAnchorMax, config.text.weaponcolor, TextAnchor.MiddleLeft, true);
            UI.Label(ref container, UI_panel_show, $"{ViewerName}", config.text.playersize, config.text.playerposAnchorMin, config.text.playerposAnchorMax, config.text.playercolor, TextAnchor.MiddleLeft);
            if(config.showinfo) {
                UI.Image(ref container, UI_panel_show, GetImage(config.info.shots.iconURL), config.info.shots.iconposAnchorMin, config.info.shots.iconposAnchorMax);
                UI.Image(ref container, UI_panel_show, GetImage(config.info.hit.iconURL), config.info.hit.iconposAnchorMin, config.info.hit.iconposAnchorMax);
                UI.Image(ref container, UI_panel_show, GetImage(config.info.headshot.iconURL), config.info.headshot.iconposAnchorMin, config.info.headshot.iconposAnchorMax);
            }
            if(config.info.accuracy.enabled) {
                UI.Panel(ref container, UI_panel_show, config.windows.bgcolor, "0 -0.15", "1 -0.03", false);
            }
            CuiHelper.DestroyUi(player, UI_panel_show);
            CuiHelper.AddUi(player, container);
            ShowPatternGUI(player, item, -1);
        }
        private void ShowPatternGUI(BasePlayer player, Item item, int count) {
            CuiElementContainer container = UI.CreateElementContainer(UI_weapon_pattern, "0 0 0 0", "0.810 0.557", "0.992 0.863");
            if(item == null) NoPattern(container);
            else {
                if(!patternData.ContainsKey(item.info.shortname)) NoPattern(container);
                else {
                    int pos = 0;
                    foreach (Vector2 point in patternData[item.info.shortname]) {
                        UI.Point(ref container, UI_weapon_pattern, config.pattern.point, config.pattern.pointsize, point, count < pos ? config.pattern.pointcolor : config.pattern.pointfirecolor);
                        pos++;
                    }
                }
            }
            CuiHelper.DestroyUi(player, UI_weapon_pattern);
            CuiHelper.AddUi(player, container);
        }
        private void NoPattern(CuiElementContainer container) {
            UI.Label(ref container, UI_weapon_pattern, Lang("NoPattern"), config.text.nopatternsize, "0 0.15", "1 1", config.text.nopatterncolor, TextAnchor.MiddleCenter);
        }
#endregion
#region CUI Helper
        public class UI {
            public static CuiElementContainer CreateElementContainer(string panelName, string color, string aMin, string aMax, string mat = "assets/content/ui/namefontmaterial.mat") {
                CuiElementContainer container = new CuiElementContainer() {
                    {
                        new CuiPanel {
                            Image = {
                                Color = color, Material = mat
                            }
                            , RectTransform = {
                                AnchorMin = aMin, AnchorMax = aMax
                            }
                            , CursorEnabled = false
                        }
                        , new CuiElement().Parent = "Overlay", panelName
                    }
                }
                ;
                return container;
            }
            static public void Panel(ref CuiElementContainer container, string panel, string color, string aMin, string aMax, bool cursor = false, string material = "assets/content/ui/uibackgroundblur-ingamemenu.mat") {
                container.Add(new CuiPanel {
                    Image = {
                        Color = color, Material = material
                    }
                    , RectTransform = {
                        AnchorMin = aMin, AnchorMax = aMax
                    }
                    , CursorEnabled = cursor
                }
                , panel);
            }
            static public void Label(ref CuiElementContainer container, string panel, string text, int size, string aMin, string aMax, string color = "1 1 1 0.6", TextAnchor align = TextAnchor.MiddleCenter, bool font = false) {
                container.Add(new CuiLabel {
                    Text = {
                        FontSize = size, Font = font? "robotocondensed-bold.ttf" : "robotocondensed-regular.ttf", Color = color, Align = align, Text = text
                    }
                    , RectTransform = {
                        AnchorMin = aMin, AnchorMax = aMax
                    }
                }
                , panel);
            }
            static public void Point(ref CuiElementContainer container, string panel, string text, int fontsize, Vector2 point, string color, bool negative = false) {
                container.Add(new CuiElement {
                    Parent = panel, Components = {
                        new CuiTextComponent {
                            Text = text, Color = color, Align = TextAnchor.MiddleCenter, FontSize = fontsize,
                        }
                        , new CuiRectTransformComponent {
                            AnchorMin = "0 0.95", AnchorMax = "1 1", OffsetMin = $"0 negative ? -point.x : point.x", OffsetMax = $"negative ? point.y : -point.y 0"
                        }
                        ,
                    }
                }
                );
            }
            static public void Button(ref CuiElementContainer container, string panel, string color, string text, int size, string aMin, string aMax, string command, TextAnchor align = TextAnchor.MiddleCenter) {
                container.Add(new CuiButton {
                    Button = {
                        Color = color, Material = "assets/content/ui/namefontmaterial.mat", Command = command, FadeIn = 0f
                    }
                    , RectTransform = {
                        AnchorMin = aMin, AnchorMax = aMax
                    }
                    , Text = {
                        Text = text, Font = "robotocondensed-regular.ttf", FontSize = size, Align = align
                    }
                }
                , panel);
            }
            static public void Image(ref CuiElementContainer container, string panel, string png, string aMin, string aMax) {
                container.Add(new CuiElement {
                    Name = CuiHelper.GetGuid(), Parent = panel, Components = {
                        new CuiRawImageComponent {
                            Png = png
                        }
                        , new CuiRectTransformComponent {
                            AnchorMin = aMin, AnchorMax = aMax
                        }
                    }
                }
                );
            }
        }
#endregion
#region Data
        void SaveData() => Interface.Oxide.DataFileSystem.WriteObject(this.Title, patternData);
        void ReadData() => patternData = Interface.Oxide.DataFileSystem.ReadObject<Dictionary <string, List <Vector2>>>(this.Title);
#endregion
#region Configuration
        private static ConfigData config = new ConfigData();
        private class ConfigData {
            [JsonProperty(PropertyName = "Use Spectate")]
            public bool spectate;
            [JsonProperty(PropertyName = "Use Arkan (Mod External: Arkan)")]
            public bool arkan = true;
            [JsonProperty(PropertyName = "Use Training (Mod External: AimTrain)")]
            public bool training;
            [JsonProperty(PropertyName = "Use ZoneManager (Mod External: ZoneManager)")]
            public bool zonemanager = true;
            [JsonProperty(PropertyName = "Active Zones (ZoneID)")]
            public List<string> zoneslist;
            [JsonProperty(PropertyName = "Show Shooting Info")]
            public bool showinfo;
            [JsonProperty(PropertyName = "Clean when reloading weapon")]
            public bool reloadClear;
            [JsonProperty(PropertyName = "Windows Config")]
            public Windows windows;
            [JsonProperty(PropertyName = "Text Display")]
            public Text text;
            [JsonProperty(PropertyName = "Info Display")]
            public Info info;
            [JsonProperty(PropertyName = "Pattern Weapons")]
            public Pattern pattern;
            [JsonProperty(PropertyName = "Recoil Player")]
            public Recoil recoil;
        }
        private class Windows {
            [JsonProperty(PropertyName = "Position AnchorMin")]
            public string posAnchorMin;
            [JsonProperty(PropertyName = "Position AnchorMax")]
            public string posAnchorMax;
            [JsonProperty(PropertyName = "Background Color")]
            public string bgcolor;
            [JsonProperty(PropertyName = "Close Text Color")]
            public string closecolor;
            [JsonProperty(PropertyName = "Close Background Color")]
            public string closebgcolor;
        }
        private class Text {
            [JsonProperty(PropertyName = "Weapon - AnchorMin")]
            public string weaponposAnchorMin;
            [JsonProperty(PropertyName = "Weapon - AnchorMax")]
            public string weaponposAnchorMax;
            [JsonProperty(PropertyName = "Weapon - Size")]
            public int weaponsize;
            [JsonProperty(PropertyName = "Weapon - Color")]
            public string weaponcolor;
            [JsonProperty(PropertyName = "Player Name - AnchorMin")]
            public string playerposAnchorMin;
            [JsonProperty(PropertyName = "Player Name - AnchorMax")]
            public string playerposAnchorMax;
            [JsonProperty(PropertyName = "Player Name - Size")]
            public int playersize;
            [JsonProperty(PropertyName = "Player Name - Color")]
            public string playercolor;
            [JsonProperty(PropertyName = "No Pattern - Size")]
            public int nopatternsize;
            [JsonProperty(PropertyName = "No Pattern - Color")]
            public string nopatterncolor;
        }
        private class Info {
            [JsonProperty(PropertyName = "Shoots Counter")]
            public InfoDetails shots;
            [JsonProperty(PropertyName = "Hit Counter")]
            public InfoDetails hit;
            [JsonProperty(PropertyName = "HeadShoot Counter")]
            public InfoDetails headshot;
            [JsonProperty(PropertyName = "Accuracy Display")]
            public Accuracy accuracy;
        }
        private class InfoDetails {
            [JsonProperty(PropertyName = "Icon URL")]
            public string iconURL;
            [JsonProperty(PropertyName = "Icon AnchorMin")]
            public string iconposAnchorMin;
            [JsonProperty(PropertyName = "Icon AnchorMax")]
            public string iconposAnchorMax;
            [JsonProperty(PropertyName = "Text AnchorMin")]
            public string textposAnchorMin;
            [JsonProperty(PropertyName = "Text AnchorMax")]
            public string textposAnchorMax;
            [JsonProperty(PropertyName = "Font Size")]
            public int textsize;
            [JsonProperty(PropertyName = "Font Color")]
            public string textcolor;
        }
        private class Accuracy {
            [JsonProperty(PropertyName = "Show Bar")]
            public bool enabled = true;
            [JsonProperty(PropertyName = "BG Color 30%")]
            public string bgcolor30 = "0.00 0.52 0.29 0.72";
            [JsonProperty(PropertyName = "BG Color 60%")]
            public string bgcolor60 = "0.97 0.51 0.14 0.72";
            [JsonProperty(PropertyName = "BG Color 80%")]
            public string bgcolor80 = "0.97 0.06 0.20 0.72";
            [JsonProperty(PropertyName = "Font Color")]
            public string textcolor;
        }
        private class Pattern {
            [JsonProperty(PropertyName = "Sets the point of the pattern")]
            public string point;
            [JsonProperty(PropertyName = "Point Size")]
            public int pointsize;
            [JsonProperty(PropertyName = "Point Color")]
            public string pointcolor;
            [JsonProperty(PropertyName = "Point Fire Color")]
            public string pointfirecolor;
        }
        private class Recoil {
            [JsonProperty(PropertyName = "Sets the point of the recoil")]
            public string point;
            [JsonProperty(PropertyName = "Point Size")]
            public int pointsize;
            [JsonProperty(PropertyName = "Point Color")]
            public string pointcolor;
        }
        private ConfigData GetDefaultConfig() {
            return new ConfigData {
                spectate = true, arkan = true, training = true, zonemanager = true, zoneslist = new List<string> {
                    "91109370", "1013570", "69696969"
                }
                , showinfo = true, reloadClear = true, windows = new Windows {
                    posAnchorMin = "0.810 0.571", posAnchorMax = "0.992 0.895", bgcolor = "0.0 0.0 0.0 0.75", closecolor = "1 1 1 1", closebgcolor = "0.87 0.0 0.0 0.9"
                }
                , text = new Text {
                    weaponposAnchorMin = "0.03 0.91", weaponposAnchorMax = "0.5 0.98", weaponsize = 12, weaponcolor = "0.8 0.8 0.8 1", playerposAnchorMin = "0.03 0.84", playerposAnchorMax = "0.6 0.94", playersize = 10, playercolor = "1 1 1 0.8", nopatternsize = 15, nopatterncolor = "1 0 0.38 1"
                }
                , info = new Info {
                    shots = new InfoDetails {
                        iconURL = "https://i.imgur.com/XhvNi3x.png", iconposAnchorMin = "0.03 0.78", iconposAnchorMax = "0.08 0.83", textposAnchorMin = "0.1 0.820", textposAnchorMax = "0.4 0.910", textsize = 12, textcolor = "0.8 0.8 0.8 0.7"
                    }
                    , hit = new InfoDetails {
                        iconURL = "https://i.imgur.com/XtiT7fO.png", iconposAnchorMin = "0.03 0.71", iconposAnchorMax = "0.08 0.76", textposAnchorMin = "0.1 0.815", textposAnchorMax = "0.4 0.885", textsize = 11, textcolor = "0.8 0.8 0.8 0.7"
                    }
                    , headshot = new InfoDetails {
                        iconURL = "https://i.imgur.com/VlMQT8F.png", iconposAnchorMin = "0.03 0.64", iconposAnchorMax = "0.08 0.69", textposAnchorMin = "0.1 0.75", textposAnchorMax = "0.4 0.82", textsize = 11, textcolor = "0.8 0.8 0.8 0.7"
                    }
                    , accuracy = new Accuracy {
                        enabled = true, bgcolor30 = "0.00 0.52 0.29 0.72", bgcolor60 = "0.97 0.51 0.14 0.72", bgcolor80 = "0.97 0.06 0.20 0.72", textcolor = "0.9 0.9 0.9 0.7"
                    }
                }
                , pattern = new Pattern {
                    point = "•", pointsize = 14, pointcolor = "1 0 0.38 1", pointfirecolor = "0.63 0.98 0.63 1.0"
                }
                , recoil = new Recoil {
                    point = "⦿", pointsize = 14, pointcolor = "1 1 1 1"
                }
                ,
            }
            ;
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                config = Config.ReadObject<ConfigData>();
                if (config == null) {
                    LoadDefaultConfig();
                }
            }
            catch {
                PrintError("Configuration file is corrupt! Check your config file at https://jsonlint.com/");
                Interface.Oxide.RootPluginManager.RemovePlugin(this);
                return;
            }
            SaveConfig();
        }
        protected override void LoadDefaultConfig() {
            config = GetDefaultConfig();
        }
        protected override void SaveConfig() {
            Config.WriteObject(config);
        }
#endregion
#region Language
        protected override void LoadDefaultMessages() {
            lang.RegisterMessages(new Dictionary<string, string> {
                ["Usage"]
                = "Usage: <color=#65C0DD>/recoil PlayerName/SteamID</color>", ["NoPattern"] = "Pattern not available.", ["DisableViewer"] = "Disabling Recoil from {0}", ["EnableViewer"] = "Checking the Recoil of <color=#65C0DD>{0}</color>", ["WithoutPermission"] = "You do not have permission to use this command!", ["ErrorSearch"] = "There was an error trying to find the specified player: <color=#FD6036>{0}</color>", ["Close"] = "Close", ["Disabled"] = "The Viewer is now disabled.", ["DisabledSpectate"] = "The Viewer is temporarily disabled in viewer mode.It will be automatically re-enabled when using <color=#65C0DD>/recoil PlayerName/SteamID</color> in Chat.", ["Empty"] = "EMPTY HANDS", ["Accuracy"] = "Hits Accuracy <color=#65C0DD>{0}%</color>", ["AutoArkanON"] = "Arkan's automatic activation by NoRecoil is now <color=#65C0DD>ON</color>.", ["AutoArkanOFF"] = "Arkan's automatic activation by NoRecoil is now <color=#65C0DD>OFF</color>.", ["AutoArkanPermission"] = "You do not have permissions to use this feature or it is disabled in the settings."
            }
            , this);
        }
        private string Lang(string key, params object[] args) => string.Format(lang.GetMessage(key, this), args);
        private void PrintToChat(BasePlayer player, string message) => Player.Message(player, "<color=#FD6036>Recoil Viewer:</color> " + message);
#endregion
    }
}

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