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

FREE BuildingUpgrade : 2.0.3 2.0.3

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("BuildingUpgrade", "https://topplugin.ru/", "2.0.3")]
    public class BuildingUpgrade : RustPlugin
    {
        #region Classes
        private class CurrentGrade
        { 
            [JsonProperty("Текущий индекс улучшения")]
            public int Grade;
            [JsonProperty("Время до де-активации")]
            public int DeActivateTime = 40;

            [JsonProperty("Таймер обновления")]
            public Timer DeTimer;

            public void UpdateTime(BasePlayer player, int time)
            {
                DeActivateTime = time;
                DeTimer?.Destroy();
                instance.UpdateTimer(player);
            }
            
            public void UpGrade(BasePlayer player, int time)
            {
				if (player==null) return;
                if (Grade >= 0 && Grade < 4)
                {
                    UpdateTime(player, time);
                    Activate(player, Grade + 1, CONF_RemoveDefaultTime);
                }
                else if (Grade >= 4)
                {
                    DeActivate(player);
                }
                else 
                {
                    player.ChatMessage($"<color=#afafaf>Неизвестная ошибка.Сообщите адмнистрации: </color><color=red>{Grade}</color>");
                    return;
                }
            }

            public void Activate(BasePlayer player, int grade, int time)
            {
				if (player==null) return;
                if (grade != Grade)
                { 
                    player.ChatMessage($"<color=#afafaf>Вы активировали режим </color><color=red>\"{CONF_GradeNames[grade]}\"</color>");
                }
                
                Grade = grade;
                DeActivateTime = time;

                if (Grade > 0)
                {
                    CuiHelper.DestroyUi(player, instance.Layer);
                    
                    var container = new CuiElementContainer();

                    var image = grade < 5 ? "UpImage" : "RemoveImage";

                    container.Add(new CuiElement
                    {
                        Name = instance.Layer,
                        Parent = "Hud",
                        Components =
                        {   
                            new CuiRawImageComponent { Png = (string) instance.ImageLibrary.Call("GetImage", image) },
                            new CuiRectTransformComponent {AnchorMin = "1 0", AnchorMax = "1 0", OffsetMin = "-413.3 11.3", OffsetMax = "-248 35.3"}
                        }
                    });

                    CuiHelper.AddUi(player, container);
                }
                else
                {
                    CuiHelper.DestroyUi(player, instance.Layer);
                }

                instance.UpdateTimer(player);
            }

            public void DeActivate(BasePlayer player) 
            {
				if (player==null) return;
                player.ChatMessage($"<color=#afafaf>Вы деактивировали режим </color><color=red>\"{CONF_GradeNames[Grade]}\"</color>");
                Grade = 0;
                Activate(player, 0, 0);
            } 
            
        }

        #endregion
 
        #region Variables

        #region Config

        #region Remove

        private const float RefundPercent = 0.5f;
        private static string CONF_RemovePermission = "GradeDestroy.Remove";
        private static bool CONF_RemoveActivated = true;
        private static int CONF_RemoveTime = 14400;
        private static int CONF_RemoveDefaultTime = 40;
        private static int CONF_RemoveHitTime = 5;
        private static bool CONF_RemoveGameFriends = false;
        private static bool CONF_RemoveFriends;
        private static bool CONF_RemoveClans;
        private static bool CONF_RemoveByCup;
        private static bool CONF_BlockRemoveOnRaid = true;

        #endregion

        #region Upgrade

        private static bool CONF_UpActivated = true;
        private static string CONF_UpPermission = "GradeDestroy.Up";
        private static bool CONF_BlockUpgradeOnRaid = true;
        private static bool CONF_EnableOnHit;

        #endregion

        #region Other
        [PluginReference] Plugin ImageLibrary;
        
        private static List<string> CONF_GradeNames = new List<string>
        {
            "отключено",
            "улучшение в дерево",
            "улучшение в камень",
            "улучшение в метал",
            "улучшение в МВК",
            "удаление построек"
        };
        
        public static Dictionary<string, ItemBlueprint> DeployableToBlueprint = new Dictionary<string, ItemBlueprint>();

        #endregion
        
        #endregion

        #region System
        
        [PluginReference] private Plugin Friends, Clans, NoEscape;
        private string Layer = "UI.Remove";
        private static BuildingUpgrade instance;

        // Список объектов с кулдаунами до удаления
        Dictionary<uint, double> removeTimers = new Dictionary<uint, double>();
        // Информация об игроках
        private Dictionary<ulong, CurrentGrade> playerGrades = new Dictionary<ulong,CurrentGrade>();

        #endregion

        #endregion
 
        #region Initialization
          
        private void OnServerInitialized()
        {
            instance = this;
            LoadDefaultConfig();

            if (Interface.Oxide.DataFileSystem.ExistsDatafile("Temporary/BuildingUpgrade/Objects"))
            {
                removeTimers = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<uint, double>>("Temporary/BuildingUpgrade/Objects");
            }
            
            timer.Every(325, SaveData);
            
            foreach (var item in ItemManager.itemList)
            {
                var itemDep = item.GetComponent<ItemModDeployable>();
                var itemBlueprint = item.GetComponent<ItemBlueprint>();
                if (itemDep != null && itemBlueprint != null)
                {
                    DeployableToBlueprint[itemDep.entityPrefab.resourcePath] = itemBlueprint;
                }
            }
			
			if (ImageLibrary){        
			
				ImageLibrary.Call("AddImage", "https://static.moscow.ovh/images/games/rust//plugins/ultimate_ui/note_remover.png", "RemoveImage");
				ImageLibrary.Call("AddImage", "https://static.moscow.ovh/images/games/rust//plugins/ultimate_ui/note_upgrade.png", "UpImage");
			}
        }

        private void Unload()
        {
            SaveData();
            foreach (var p in BasePlayer.activePlayerList) CuiHelper.DestroyUi(p, Layer);
        }

        private void SaveData()
        {
            Interface.Oxide.DataFileSystem.WriteObject("Temporary/BuildingUpgrade/Objects", removeTimers);
        }
        
        protected override void LoadDefaultConfig()
        {
            GetConfig("Удаление построек", "Разрешать игрокам удалять постройки", ref CONF_RemoveActivated);
            GetConfig("Удаление построек", "Разрешение для удаления построек", ref CONF_RemovePermission);
            GetConfig("Удаление построек", "Лимит времени для удаления (0 - бесконечно)", ref CONF_RemoveTime);
            GetConfig("Удаление построек", "Разрешить удалять постройки друзей", ref CONF_RemoveFriends);
            GetConfig("Удаление построек", "Разрешить удалять постройка со-кланов", ref CONF_RemoveClans);
            GetConfig("Удаление построек", "Разрешить удалять при авторизации в шкафу", ref CONF_RemoveByCup);
            GetConfig("Удаление построек", "Запрещать удалять во время рейда", ref CONF_BlockRemoveOnRaid);
            
            GetConfig("Улучшение построек", "Разрешать игрокам улучшать постройки", ref CONF_UpActivated);
            GetConfig("Улучшение построек", "Разрешение для улучшения построек", ref CONF_UpPermission);
            GetConfig("Улучшение построек", "Время автоматического включения улучшения", ref CONF_RemoveHitTime);
            GetConfig("Улучшение построек", "Включать режим автоматического улучшения при ручном улучшения", ref CONF_EnableOnHit);
            GetConfig("Улучшение построек", "Запрещать улучшать во время рейда", ref CONF_BlockUpgradeOnRaid);
            

            GetConfig("Остальное", "Отображение имён улучшения", ref CONF_GradeNames);
            
            Config.Save();
        }

        #endregion

        #region Functions

        private string CanRemove(BasePlayer player, BaseEntity entity)
        {
			if (player==null || entity==null) return "Ошибка";
            if (!player.IsBuildingAuthed())
            { 
                return "<color=#afafaf>Вы не можете удалять постройки без шкафа</color>"; 
            }
             
            if (!player.CanBuild())
            {
                return "<color=#afafaf>Вы не можете удалять в зоне действия</color><color=red>чужого шкафа</color>!"; 
            }

            var time = GetRaidBlockTime(player.userID);
             
            if (time > 0)
            {
                return $"<color=#afafaf>Вы не можете улучшать постройки! Подождите: {FormatTime(TimeSpan.FromSeconds(time))}</color>";
            }

            double maxRemoveTime;
            if (CONF_RemoveTime != 0 && removeTimers.TryGetValue(entity.net.ID, out maxRemoveTime) && maxRemoveTime <= CurrTimestamp())
            { 
                return "<color=#afafaf>Вышло время удаления данного объекта!</color>";
            }

            bool isOwner = entity.OwnerID == player.userID;
            bool areFriends = (bool) (Friends?.Call("ApiIsFriend", player.userID, entity.OwnerID) ?? false);
            List<string> areClanMates = (List<string>) (Clans?.Call("GetClanMembers", player.userID) ?? new List<string>());
            
            if (CONF_RemoveByCup || CONF_RemoveFriends && areFriends || CONF_RemoveClans && areClanMates.Contains(entity.OwnerID.ToString()) || isOwner)
            {
                return "";
            }

            return "<color=#afafaf>Вы можете удалять свои постройки, а также постройки друзей!</color>";
        }

        private string TryUpgrade(BasePlayer player, BuildingBlock block, CurrentGrade currentGrade)
        {
			if (player==null || block==null) return "Ошибка";
            if (currentGrade.Grade <= (int) block.lastGrade )
                return "";

            var time = GetRaidBlockTime(player.userID);
            
            if (time > 0)
            {
                return $"<color=#afafaf>Вы не можете улучшать постройки! Подождите: {FormatTime(TimeSpan.FromSeconds(time))}</color>";
            }

            var building = BuildingManager.server.GetBuilding(block.buildingID);
            if (building != null && !building.HasBuildingPrivileges())
            {
                return $"<color=#afafaf>Вы не можете использовать автоапгрейд <color=red>без шкафа</color>.</color>";
            }

            if (CONF_BlockUpgradeOnRaid && NoEscape)
            {
                var blockTime = (bool) (NoEscape?.Call("IsRaidBlocked", player) ?? false);
                if (blockTime)
                {
                    currentGrade.DeActivate(player); 
                    return "<color=#afafaf>Вы не можете авто-улучшать постройки во время рейда</color>!";
                }
            }
            
            if (block.SecondsSinceAttacked < 30)
            { 
                return $"<color=#afafaf>Это объект можно будет улучшить через {FormatTime(TimeSpan.FromSeconds(30 - (int) block.SecondsSinceAttacked), maxSubstr:2)}</color>";
            }

            if (block.blockDefinition.checkVolumeOnUpgrade &&
                DeployVolume.Check(block.transform.position, block.transform.rotation, 
                    PrefabAttribute.server.FindAll<DeployVolume>(block.prefabID), ~(1 << block.gameObject.layer)))
            {
                return $"<color=#afafaf>Улучшение данного объекта чем-то заблокированно</color>";
            }

            
            foreach (var check in block.blockDefinition.grades[currentGrade.Grade].costToBuild)
            {
                if (player.inventory.GetAmount(check.itemid) < check.amount)
                {
                    CuiHelper.DestroyUi(player, Layer);
                    currentGrade.DeActivate(player);
                    return "<color=#afafaf>У вас не хватает ресурсов для автоматического улучшения!</color>";
                }
            }
            
            foreach (var check in block.blockDefinition.grades[currentGrade.Grade].costToBuild)
            {
                player.inventory.Take(null, check.itemid, (int) check.amount);
                player.Command("note.inv", check.itemid, check.amount * -1f);
            }
            
            block.SetGrade((BuildingGrade.Enum) currentGrade.Grade);
            block.UpdateSkin(); 
            block.SetHealthToMax();
            block.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
            currentGrade.UpdateTime(player, CONF_RemoveDefaultTime);
            
            return "";
        }

        private void UpdateTimer(BasePlayer player)
        {
            CurrentGrade currentGrade = GetPlayerCurrentGrade(player);
            if (currentGrade.Grade == 0)
            {
                CuiHelper.DestroyUi(player, Layer);
                return;
            }
            
            CuiHelper.DestroyUi(player, Layer + ".Text");
            
            CuiElementContainer container = new CuiElementContainer();
            
            container.Add(new CuiLabel
            {
                Text = { Text = $"{CONF_GradeNames[currentGrade.Grade].ToUpper()}", FontSize = 12, Font = "robotocondensed-bold.ttf", Align = TextAnchor.MiddleCenter },
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "27.3 0" }
            }, Layer, Layer + ".Text");

            CuiHelper.AddUi(player, container);
              
            currentGrade.DeActivateTime--;
            if (currentGrade.DeActivateTime < 0)
            { 
                currentGrade.DeActivate(player);
                CuiHelper.DestroyUi(player, Layer);
                return;
            }
            
            currentGrade.DeTimer?.Destroy();
            currentGrade.DeTimer = timer.Once(1, () => UpdateTimer(player));
        }

        #endregion

        #region Commands

        [ConsoleCommand("building.upgrade")]
        void cmdConsoleUpgrade(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection?.player as BasePlayer;

            if (player == null) return;

            CurrentGrade currentGrade = GetPlayerCurrentGrade(player);
            currentGrade.UpGrade(player, CONF_RemoveDefaultTime); 
        }
        
        [ChatCommand("remove")]
        private void cmdChatRemove(BasePlayer player, string command, string[] args)
        {
            if (player == null) return;
            if (!CONF_RemoveActivated)
                return;
            
            CurrentGrade currentGrade = GetPlayerCurrentGrade(player);

            if (currentGrade.Grade == 5)
            {
                currentGrade.DeActivate(player);
            }
            else
            {
                currentGrade.Activate(player, 5, CONF_RemoveDefaultTime);
            }
        }

        [ChatCommand("up")]
        private void cmdChatUpgrade(BasePlayer player, string command, string[] args)
        {
            if (player == null) return;
            if (!CONF_UpActivated)
                return;

            CurrentGrade currentGrade = GetPlayerCurrentGrade(player);

            switch (args.Length)
            {
                case 0:
                {
                    currentGrade.UpGrade(player, CONF_RemoveDefaultTime);
                    break;
                }
                case 1:
                {
                    int newGrade;
                    if (!int.TryParse(args[0], out newGrade) || newGrade < 0 || newGrade > 4)
                    {
                        SendReply(player, $"Введенный уровень улучшение <color=#D500C3>не существует</color>!\n" +
                                                $"Попробуйте:\n" +
                                                $"\n" + 
                                                $"<color=#afafaf>0</color> => Отключить\n" +
                                                $"<color=#afafaf>1</color> => В дерево\n" +
                                                $"<color=#afafaf>2</color> => В камень\n" +
                                                $"<color=#afafaf>3</color> => В метал\n" +
                                                $"<color=#afafaf>4</color> => В МВК");
                        return;
                    }
                    currentGrade.Activate(player, newGrade, CONF_RemoveDefaultTime);
                    break;
                }
                default:
                {
                    cmdChatUpgrade(player, command, new string[] { });
                    return;
                }
            }
        }

        #endregion

        #region Hooks

        private void OnEntityBuilt(Planner plan, GameObject go)
        {
            if (plan == null) return;
            BasePlayer player = plan?.GetOwnerPlayer();
            if (player == null)
                return;

            var baseEnt = go.ToBaseEntity();
            BuildingBlock block = go.ToBaseEntity().GetComponent<BuildingBlock>();

            if (CONF_RemoveTime != 0 && (block != null || baseEnt is Door))
            {
                removeTimers.Add(baseEnt.net.ID, CurrTimestamp() + CONF_RemoveTime);
            }
            
            if (block == null) 
                return;

            var currentGrade = GetPlayerCurrentGrade(player);
            if (currentGrade.Grade <= 0 || currentGrade.Grade > 4)
                return;

            var result = TryUpgrade(player, block, currentGrade);
            if (result != string.Empty)
            {
                player.ChatMessage(result);
            }
        }
        
        object OnHammerHit(BasePlayer player, HitInfo info)
        {
            if (info == null)
                return null;
            
            var currentGrade = GetPlayerCurrentGrade(player);

            var ent = info.HitEntity;
            if (ent == null)
                return null;
            
            if (currentGrade.Grade == 5)
            {
                if ((ent is BuildingBlock || DeployableToBlueprint.ContainsKey(ent.PrefabName)) && !ent.IsDestroyed)
                {
                    var tryRemoveResult = CanRemove(player, ent);
                    if (tryRemoveResult != "")
                        SendReply(player, tryRemoveResult);
                    else
                        RemoveEntity(player, ent);
                    return false;
                }
            }
            else if (currentGrade.Grade != 0)
            {
                var block = ent as BuildingBlock;
                if (block != null && HasUpgradePrivilege(player, block))
                {
                    var tryUpgradeResult = TryUpgrade(player, block, currentGrade);
                    if (tryUpgradeResult != string.Empty)
                        SendReply(player, tryUpgradeResult);
                    return false;
                }
            }
            else
            {
                if (CanRemove(player, ent) == string.Empty)
                {
                    var block = ent as BuildingBlock;
                    if (block != null && HasUpgradePrivilege(player, block))
                    {
                        double maxRemoveTime;
                        if (removeTimers.TryGetValue(block.net.ID, out maxRemoveTime) && player.SecondsSinceAttacked > 10) 
                        {
                            double leftRemove = maxRemoveTime - CurrTimestamp();
                            if (leftRemove < 0) 
                            {
                                SendReply(player, "<color=#afafaf>Время удаления данного объекта</color><color=#D500C3>закончилось</color>!");
                            }
                            else
                            {
                                SendReply(player, $"<color=#afafaf>Через</color><color=red>{FormatTime(TimeSpan.FromSeconds(leftRemove), maxSubstr:2)}</color><color=#afafaf> вы не сможете удалить этот объект!</color>");
                            }
                            
                            player.Hurt(0);
                        }
                    }
                }
            }
            
            return null;
        }

        private bool HasUpgradePrivilege(BasePlayer player, BaseEntity entity)
        {
            return !player.IsBuildingBlocked(entity.transform.position, entity.transform.rotation, entity.bounds);
        }

        object OnStructureUpgrade(BaseCombatEntity entity, BasePlayer player, BuildingGrade.Enum grade)
        {
			if (player==null) return null;
            if (CONF_EnableOnHit && permission.UserHasPermission(player.UserIDString, CONF_UpPermission))
            {
                CurrentGrade currentGrade = GetPlayerCurrentGrade(player);
                currentGrade.Activate(player, (int) grade, CONF_RemoveHitTime);
            }

            if (player.SecondsSinceAttacked > 10)
            { 
                SendReply(player, $"<color=#afafaf>Вы можете удалить построенный объект в течении </color><color=red>{FormatTime(TimeSpan.FromSeconds(CONF_RemoveTime), maxSubstr:2)}</color>");
                player.Hurt(0);
            }
            return null;
        }

        #endregion

        #region Utils
        
        private void RemoveEntity(BasePlayer player, BaseEntity hitEntity)
        {
			if (player==null || hitEntity==null) return;
            RefundEntity(player, hitEntity);
            
            var storageContainer = hitEntity as StorageContainer;
            if (storageContainer != null)
            {
                storageContainer.DropItems();
            }

            removeTimers.Remove(hitEntity.net.ID);
            hitEntity.Kill(BaseNetworkable.DestroyMode.Gib);
        }

        private static void RefundEntity(BasePlayer player, BaseEntity entity)
        {
			if (player==null || entity==null) return;
            if (entity.name == "assets/prefabs/deployable/planters/planter.small.deployed.prefab")
            {
                return;
            }

            List<ItemAmount> ingredientList = null;

            var entityBb = entity as BuildingBlock;
            ItemBlueprint itemBp;
            if (DeployableToBlueprint.TryGetValue(entity.name, out itemBp))
            {
                ingredientList = itemBp.ingredients;
            }
            else if (entityBb != null)
            {
                ingredientList = entityBb.blockDefinition.grades[(int) entityBb.grade].costToBuild;
            }

            if (ingredientList == null || ingredientList.Count == 0)
            {
                return;
            }
            
            foreach (ItemAmount ingredient in ingredientList)
            {
                var amount = (int)ingredient.amount;
                amount = amount == 0 ? 1 : amount;
                amount = (int) Math.Round( (double) amount * RefundPercent);

                if (amount <= 0)
                {
                    continue;
                }

                Item item = ItemManager.CreateByItemID(ingredient.itemid, amount);
                player.GiveItem(item);
            }
        }
        
        private CurrentGrade GetPlayerCurrentGrade(BasePlayer player)
        {
            CurrentGrade currentGrade;
            if (!playerGrades.TryGetValue(player.userID, out currentGrade))
                currentGrade = playerGrades[player.userID] = new CurrentGrade();
            return currentGrade;
        }

        public double GetRaidBlockTime(ulong userID)
        {
            if (!plugins.Find("NoEscape")) return 0;
            var time = plugins.Find("NoEscape").CallHook("ApiGetTime", userID);
            return Convert.ToDouble(time);
        }

        private static string HexToRustFormat(string hex)
        {
            if (string.IsNullOrEmpty(hex))
            {
                hex = "#FFFFFFFF";
            }

            var str = hex.Trim('#');

            if (str.Length == 6)
                str += "FF";

            if (str.Length != 8)
            {
                throw new Exception(hex);
            }

            var r = byte.Parse(str.Substring(0, 2), NumberStyles.HexNumber);
            var g = byte.Parse(str.Substring(2, 2), NumberStyles.HexNumber);
            var b = byte.Parse(str.Substring(4, 2), NumberStyles.HexNumber);
            var a = byte.Parse(str.Substring(6, 2), NumberStyles.HexNumber);

            Color color = new Color32(r, g, b, a);

            return $"{color.r:F2} {color.g:F2} {color.b:F2} {color.a:F2}";
        }
        
        public static string FormatTime(TimeSpan time, int maxSubstr = 5)
        {
            string result = string.Empty;

            int i = 0;
            if (time.Days != 0 && i < maxSubstr)
            {
                if (!string.IsNullOrEmpty(result))
                    result += " ";

                result += $"{Format(time.Days, "дней", "дня", "день")}";
                i++;
            }

            if (time.Hours != 0 && i < maxSubstr)
            {
                if (!string.IsNullOrEmpty(result))
                    result += " ";

                result += $"{Format(time.Hours, "часов", "часа", "час")}";
                i++;
            }

            if (time.Minutes != 0 && i < maxSubstr)
            {
                if (!string.IsNullOrEmpty(result))
                    result += " ";

                result += $"{Format(time.Minutes, "минут", "минуты", "минута")}";
                i++;
            }

            if (time.Seconds != 0 && i < maxSubstr)
            {
                if (!string.IsNullOrEmpty(result))
                    result += " ";

                result += $"{Format(time.Seconds, "секунд", "секунды", "секунда")}";
            }

            return result;
        }
        
        private static string Format(int units, string form1, string form2, string form3 )
        {
            var tmp = units % 10;

            if (units >= 5 && units <= 20 || tmp >= 5 && tmp <= 9)
                return $"{units} {form1}";

            if (tmp >= 2 && tmp <= 4)
                return $"{units} {form2}";

            return $"{units} {form3}";
        }
        
        private bool GetConfig<T>(string mainMenu, string key, ref T var)
        {
            if (Config[mainMenu, key] != null)
            {
                var = Config.ConvertValue<T>(Config[mainMenu, key]);
                return false;
            }

            Config[mainMenu, key] = var;
            return true;
        }
        
        private static DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0);
        private static double CurrTimestamp() => DateTime.UtcNow.Subtract(epoch).TotalSeconds;

        #endregion
    }
}

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