C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System.Text;
using System.IO;
using Object = System.Object;
using Time = UnityEngine.Time;
using Pool = Facepunch.Pool;
using Oxide.Core;
using Oxide.Core.Plugins;
using UnityEngine;
using Newtonsoft.Json;
using System.Collections;
using Physics = UnityEngine.Physics;
using System;
using Oxide.Game.Rust.Cui;
using System.Text.RegularExpressions;
using System.Linq;
using UnityEngine.Networking;
using System.Collections.Generic;
namespace Oxide.Plugins {
[Info("IQGradeRemove", "BlackPlugin.ru", "10.0.1")]
[Description("IQGradeRemove")]
public class IQGradeRemove : RustPlugin {
private void HandleBuildingReturn(BasePlayer player, StabilityEntity buildingBlock, Configuration.RemovePreset.ReturnedSettings.Building BuildingSettings) {
Single PercentReturn = BuildingSettings.UsePercentHealts ? buildingBlock.health / buildingBlock.MaxHealth() : BuildingSettings.PercentReturn / 100.0f;
foreach (ItemAmount CostReturned in buildingBlock.BuildCost()) {
Int32 amount = Mathf.FloorToInt(CostReturned.amount * PercentReturn);
if (amount <= 0) continue;
player.GiveItem(ItemManager.Create(CostReturned.itemDef, amount));
}
}
private const String PermissionsUpHqm = "iqgraderemove.uphmetal";
private void ConsoleCMDRemove(ConsoleSystem.Arg arg) {
BasePlayer player = arg.Player();
if (player == null) return;
ControllerGradeRemove(player, "5");
}
private const String PermissionsUpStone = "iqgraderemove.upstones";
private void DrawUI_Types(BasePlayer player, Int32 Index, LocalRepositoryUser repositoryUser) {
if (_interface == null) return;
String Interface = InterfaceBuilder.GetInterface("UI_TypeElement");
if (Interface == null) return;
ActionType type = (ActionType)Index;
String NameType = type.ToString();
Boolean isPermissionType = LocalRepository[player].HasPermissionTypes(player, Index);
String cmdType = isPermissionType ? type != ActionType.Remove ? $"upgrade.func {Index}" : $"{config.CommandsList.RemoveCommands[0]}" : String.Empty;
String iconType = isPermissionType ? (type switch {
ActionType.Wood => "WOOD", ActionType.Stone => "STONE", ActionType.Metal => "METAL", ActionType.Hqm => "HQM", _ => "REMOVE"
}
) : "NO_PERMISSION";
GenerateOffsets(config.InterfaceControllers.TypeElement.TypesElements.OffsetMin, config.InterfaceControllers.TypeElement.TypesElements.OffsetMax, config.InterfaceControllers.TypeElement.OffsetBetweenElements, Index, out String newOffsetMin, out String newOffsetMax);
Interface = Interface.Replace("%NAME_TYPE%", NameType);
Interface = Interface.Replace("%TYPE_ICON%", _imageUI.GetImage(iconType));
Interface = Interface.Replace("%COMMAND_TYPE%", cmdType);
Interface = Interface.Replace("%OFFSET_MIN%", newOffsetMin);
Interface = Interface.Replace("%OFFSET_MAX%", newOffsetMax);
CuiHelper.AddUi(player, Interface);
if (type == repositoryUser.selectedType) DrawUI_Types_Selected(player, NameType);
}
Object OnStructureUpgrade(BaseCombatEntity entity, BasePlayer player, BuildingGrade.Enum grade) {
BuildingBlock buildingBlock = entity as BuildingBlock;
if (buildingBlock == null) return null;
if(entity.prefabID is 132854323 or 3285432) return null;
Boolean isAutoBaseUpgrade = AutoBaseUpgrade != null && AutoBaseUpgrade.Call<Boolean>("IsBaseUpgradeProcess", entity.GetBuildingPrivilege());
String canUpgrade = config.disableControllRadialMenu || isAutoBaseUpgrade ? String.Empty : CanUpgrade(player, buildingBlock, LocalRepository[player], grade);
if (String.IsNullOrWhiteSpace(canUpgrade)) {
UInt64 SkinBuilding = GetBuildingSkin(player, grade);
buildingBlock.SetHealthToMax();
if (grade == BuildingGrade.Enum.Metal && SkinBuilding == 10221) buildingBlock.SetCustomColour(GetShippingContainerBlockColourForPlayer(player));
return null;
}
MessageGameTipsError(player, canUpgrade);
return true;
}
private class ImageUI {
private const String _path = "IQSystem/IQGradeRemove/Images/";
private const String _printPath = "data/" + _path;
private readonly Dictionary<String, ImageData> _images = new() {
{
"HUDPANEL", new ImageData()
}
, {
"SELECTED_ELEMENT", new ImageData()
}
, {
"NO_PERMISSION", new ImageData()
}
, {
"ALL_BUTTON", new ImageData()
}
, {
"ALL", new ImageData()
}
, {
"WOOD", new ImageData()
}
, {
"STONE", new ImageData()
}
, {
"METAL", new ImageData()
}
, {
"HQM", new ImageData()
}
, {
"REMOVE", new ImageData()
}
,
}
;
private enum ImageStatus {
NotLoaded, Loaded, Failed
}
private class ImageData {
public ImageStatus Status = ImageStatus.NotLoaded;
public string Id {
get;
set;
}
}
public string GetImage(string name) {
ImageData image;
if (_images.TryGetValue(name, out image) && image.Status == ImageStatus.Loaded) return image.Id;
return null;
}
public void DownloadImage() {
if (config.InterfaceControllers.closeUIUsed) _images.TryAdd("CLOSE_BUTTON", new ImageData());
KeyValuePair<string, ImageData>? image = null;
foreach (KeyValuePair<string, ImageData> img in _images) {
if (img.Value.Status == ImageStatus.NotLoaded) {
image = img;
break;
}
}
if (image != null) {
ServerMgr.Instance.StartCoroutine(ProcessDownloadImage(image.Value));
}
else {
List<String> failedImages = new List<string>();
foreach (KeyValuePair<String, ImageData> img in _images) {
if (img.Value.Status == ImageStatus.Failed) {
failedImages.Add(img.Key);
}
}
if (failedImages.Count > 0) {
String images = String.Join(", ", failedImages);
_.PrintError(LanguageEn ? $"Failed to load the following images: {images}.Perhaps you did not upload them to the '{_printPath}' folder.Images - https://drive.google.com/drive/folders/1MYmWgN-KHWQhfFxNiweQo9h3SfPwsxDS" : $"Не удалось загрузить следующие изображения: {images}.Возможно, вы не загрузили их в папку '{_printPath}'.Картинки - https://drive.google.com/drive/folders/1MYmWgN-KHWQhfFxNiweQo9h3SfPwsxDS");
Interface.Oxide.UnloadPlugin(_.Name);
}
else {
_.Puts(LanguageEn ? $"{_images.Count} images downloaded successfully!" : $"{_images.Count} изображений успешно загружено!");
_interface = new InterfaceBuilder();
}
}
}
public void UnloadImages() {
foreach (KeyValuePair<string, ImageData> item in _images) if(item.Value.Status == ImageStatus.Loaded) if (item.Value?.Id != null) FileStorage.server.Remove(uint.Parse(item.Value.Id), FileStorage.Type.png, CommunityEntity.ServerInstance.net.ID);
_images?.Clear();
}
private IEnumerator ProcessDownloadImage(KeyValuePair<string, ImageData> image) {
string url = "file://" + Interface.Oxide.DataDirectory + Path.DirectorySeparatorChar + _path + image.Key + ".png";
using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url)) {
yield return www.SendWebRequest();
if (www.result is UnityWebRequest.Result.ConnectionError or UnityWebRequest.Result.ProtocolError) {
image.Value.Status = ImageStatus.Failed;
}
else {
Texture2D tex = DownloadHandlerTexture.GetContent(www);
image.Value.Id = FileStorage.server.Store(tex.EncodeToPNG(), FileStorage.Type.png, CommunityEntity.ServerInstance.net.ID).ToString();
image.Value.Status = ImageStatus.Loaded;
UnityEngine.Object.DestroyImmediate(tex);
}
DownloadImage();
}
}
}
private const String PermissionAllObjectsBack = "iqgraderemove.allobjectsback";
void GenerateOffsets(String OffsetMin, String OffsetMax, Single OffsetBetween, Int32 Index, out String newOffsetMin, out String newOffsetMax) {
String[] minParts = OffsetMin.Split(' ');
String[] maxParts = OffsetMax.Split(' ');
if (minParts.Length != 2 || maxParts.Length != 2) {
throw new ArgumentException(LanguageEn ? "OffsetMin and OffsetMax must have exactly two parts separated by a space" : "OffsetMin и OffsetMax должны состоять ровно из двух частей, разделенных пробелом");
}
Single min0 = float.Parse(minParts[0]);
Single min1 = float.Parse(minParts[1]);
Single max0 = float.Parse(maxParts[0]);
Single max1 = float.Parse(maxParts[1]);
newOffsetMin = $"{min0 - (OffsetBetween * (Index - 1))} {min1}";
newOffsetMax = $"{max0 - (OffsetBetween * (Index - 1))} {max1}";
}
private const String PermissionsRemoveAdmin = "iqgraderemove.removeadmin";
private void OnPlayerConnected(BasePlayer player) => RegisteredPlayer(player);
private void ControllerGradeRemove(BasePlayer player, String ArgNumber = "") {
if (String.IsNullOrWhiteSpace(ArgNumber)) {
LocalRepository[player].ActionAssignment(player);
return;
}
if (!Int32.TryParse(ArgNumber, out Int32 actionType)) return;
LocalRepository[player].ActionAssignment(player, actionType);
}
private List<BasePlayer> playerAlerUp = new();
private const String PermissionsUpMetal = "iqgraderemove.upmetal";
private Boolean IsFriends(BasePlayer player, BasePlayer.EncryptedValue<UInt64> targetPlayerID) => IsFriends(player, targetPlayerID.Get());
private Boolean IsFriends(BasePlayer player, UInt64 targetPlayerID) {
List<UInt64> FriendList = GetFriendList(player);
try {
return FriendList != null && FriendList.Contains(targetPlayerID);
}
finally {
Pool.FreeUnmanaged(ref FriendList);
}
}
private const String PermissionsDistanceFunc = "iqgraderemove.distancefunc";
private String Format(Int32 units, String form) {
Int32 tmp = units % 10;
if (units >= 5 && units <= 20 || tmp >= 5 && tmp <= 9) return $"{units}{form}";
if (tmp >= 2 && tmp <= 4) return $"{units}{form}";
return $"{units}{form}";
}
private class Configuration {
[JsonProperty(LanguageEn ? "Use notifications with instructions when using a chat command to delete or improve" : "Использовать уведомления с инструкцией при использовании чат команды на удаление или улучшение")]
public Boolean useInstructionAlert;
[JsonProperty(LanguageEn ? "Duration of the selected element (improvement/removal) in seconds" : "Время действия выбранного элемента (улучшени/удаления) в секундах")]
public Int32 ConfigActiveGradeRemove;
internal class RemovePreset {
[JsonProperty(LanguageEn ? "Allow building remove after recent damage" : "Разрешить удаление постройки после недавно нанесенного урона")]
public Boolean RemoveSecondsAttacks;
[JsonProperty(LanguageEn ? "Disable remove during raid block" : "Запретить удаление во время рейдблока")]
public Boolean NoRemoveRaidBlock;
[JsonProperty(LanguageEn ? "Only friends can remove structures (otherwise, anyone who has access to the cupboard)" : "Удалять постройки могут только друзья (Иначе все,кто есть в шкафу)")]
public Boolean RemoveOnlyFriends;
[JsonProperty(LanguageEn ? "Items that cannot be removed (Shortname)" : "Предметы, которые нельзя удалить (Shortname)")]
public List<String> NoRemoveItems = new List<String>();
[JsonProperty(LanguageEn ? "Cooldown settings before removing a new object" : "Настройка перезарядки перед удалением нового объекта")]
public CooldownController CooldownRemove = new CooldownController();
[JsonProperty(LanguageEn ? "Temporary construction removal restriction (Exapmle : After placing the object, it won't be possible to remove it for a certain amount of time)" : "Временный запрет на удаление постройки (Например : После установки объекта, его N количество времени нельзя будет удалить)")]
public BlockRemoveBuilding TemporaryBlockBuildRemove = new BlockRemoveBuilding();
[JsonProperty(LanguageEn ? "Complete prohibition of object removal (For example: After 3 hours of placing the object, it cannot be removed at all)" : "Полный запрет на удаление объекта (Например : Через 3 часа после установки объекта, его нельзя будет удалить вообще)")]
public BlockRemoveBuilding FullBlockBuildRemove = new BlockRemoveBuilding();
[JsonProperty(LanguageEn ? "Resource and item return settings after deletion" : "Настройка возврата ресурсов и предметов после удаления")]
public ReturnedSettings ReturnedRemoveSettings = new ReturnedSettings();
internal class BlockRemoveBuilding {
[JsonProperty(LanguageEn ? "Use lock function" : "Использовать функцию блокировки")]
public Boolean UseBlock;
[JsonProperty(LanguageEn ? "Time in seconds" : "Время в секундах")]
public Int32 TimeRemove;
[JsonProperty(LanguageEn ? "Privilege-based configuration [iqgraderemove.name = time (in seconds)]" : "Настройка по привилегиям [iqgraderemove.name = время (в секундах)]")]
public Dictionary<String, Int32> PermissionTime = new Dictionary<String, Int32>();
}
internal class ReturnedSettings {
[JsonProperty(LanguageEn ? "Return attached items to the item being removed (For example, a combination lock to the door) (Return of items or % of resources on deletion must be enabled)" : "Возвращать прикрепленные предметы к удаляемому предмету (Например кодовый замок к двери) (Должен быть включен возврат предметов или % ресурсов при удалении)")]
public Boolean returnedChildItems;
[JsonProperty(LanguageEn ? "Resource return settings for building deletion" : "Настройка возврата ресурсов за удаление строений")]
public Building BuildingSettings = new Building();
[JsonProperty(LanguageEn ? "Resource/item return settings for item deletion" : "Настройка возврата ресурсов/предметов за удаление предметов")]
public Items ItemsSettings = new Items();
internal class Building {
[JsonProperty(LanguageEn ? "Enable resource return for building deletion" : "Возвращать ресурсы за удаление строений")]
public Boolean UseReturned;
[JsonProperty(LanguageEn ? "Use return percentage based on building durability (disregards 'Resource return percentage for building deletion')" : "Использовать процент возврата в зависимости от количество прочности строения (не будет учитываться пункт 'Процент возврата ресурсов за удаление строений')")]
public Boolean UsePercentHealts;
[JsonProperty(LanguageEn ? "Resource return percentage for building deletion (regardless of building durability)" : "Процент возврата ресурсов за удаление строений (вне зависимости от количества прочности строения)")]
public Int32 PercentReturn;
}
internal class Items {
[JsonProperty(LanguageEn ? "Return items after deletion, otherwise return % of item's resources (if craftable)" : "Возвращать предметы после удаления, иначе будет возвращаться % ресурсов от предмета (если его возможно крафтить)")]
public Boolean UseReturnedItem;
[JsonProperty(LanguageEn ? "Use return percentage based on item durability (disregards 'Resource return percentage for item deletion')" : "Использовать процент возврата в зависимости от количество прочности строения (не будет учитываться пункт 'Процент возврата ресурсов за удаление предмета')")]
public Boolean UsePercentHealts;
[JsonProperty(LanguageEn ? "Resource return percentage for item deletion (if percentage return is enabled)" : "Процент возврата ресурсов за удаление предмета (если включен возврат процента)")]
public Int32 PercentReturn;
[JsonProperty(LanguageEn ? "Reduce item condition upon return" : "Снижать состояние предмета при возврате")]
public Boolean UseDamageReturned;
[JsonProperty(LanguageEn ? "Items to be ignored after deletion - they will simply be deleted without any return of items or resources (Shortname)" : "Предметы, которые игнорируются после удаления - они просто удалятся без возврата предмета или ресурсов (Shortname)")]
public List<String> ShortnameNoteReturned = new List<String>();
}
}
}
internal class CommandPresets {
[JsonProperty(LanguageEn ? "List of commands to upgrade" : "Список команд для улучшения")]
public List<String> UpgradeCommands = new List<String>();
[JsonProperty(LanguageEn ? "List of commands to remove" : "Список команд для удаления")]
public List<String> RemoveCommands = new List<String>();
}
internal class CooldownController {
[JsonProperty(LanguageEn ? "Use cooldown before action" : "Использовать перезарядку перед действием")]
public Boolean UseCooldown;
[JsonProperty(LanguageEn ? "Time in seconds" : "Время в секундах")]
public Single SecondCooldown;
}
[JsonProperty(LanguageEn ? "Upgrade settings" : "Настройка улучшения")]
public UpgradePreset UpgradePresets = new UpgradePreset();
[JsonProperty(LanguageEn ? "Setting UI" : "Настройка UI")]
public InterfaceController InterfaceControllers = new InterfaceController();
[JsonProperty(LanguageEn ? "Remove settings" : "Настройка удаления")]
public RemovePreset RemovePresets = new RemovePreset();
[JsonProperty(LanguageEn ? "Disable the connection of the plugin with the radial RUST menu (true - yes/false - no)" : "Отключить связь плагина с радиальным меню RUST (true - да/false - нет)")]
public Boolean disableControllRadialMenu;
public static Configuration GetNewConfiguration() {
return new Configuration {
disableControllRadialMenu = false, useInstructionAlert = false, UseDistanceFunc = false, ConfigResetInterface = true, ConfigActiveGradeRemove = 60, IsCheckPermission = false, InterfaceControllers = new InterfaceController() {
StaticPanel = new InterfaceController.Coordinates() {
AnchorMin = "0 0", AnchorMax = "0 0", OffsetMin = "58.333 25", OffsetMax = "335.667 73"
}
, TypeElement = new InterfaceController.TypeElements() {
OffsetBetweenElements = -44.5f, SizeSelectedElement = "21.333", TypesElements = new InterfaceController.Coordinates() {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-132 -17.333", OffsetMax = "-97 17.333",
}
}
, AllObject = new InterfaceController.AllObjects {
AllObjectsButton = new InterfaceController.Coordinates {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-188.46712 -24", OffsetMax = "-140.467 24"
}
, SizeSelectedElement = "21.333",
}
, TimerElements = new InterfaceController.TimerElement() {
TimerPosition = new InterfaceController.Coordinates() {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "90.878 -18.828", OffsetMax = "137.255 18.828",
}
, SizeTimer = 30,
}
}
, CommandsList = new CommandPresets() {
UpgradeCommands = new List<String>() {
"up", "upgrade", "grade", "bgrade"
}
, RemoveCommands = new List<String>() {
"remove", "rem",
}
}
, UpgradePresets = new UpgradePreset() {
NoGradeWithoutCupboard = false, UpgradeSecondsAttacks = false, RepairToGrade = true, NoGradeRaidBlock = true, BackUpgrade = false, BackUpgradeReturnedItem = false, BackUpgradeReturnedItemPercent = 50, CooldownUpgrade = new CooldownController() {
UseCooldown = false, SecondCooldown = 30,
}
}
, RemovePresets = new RemovePreset() {
RemoveSecondsAttacks = false, NoRemoveRaidBlock = true, RemoveOnlyFriends = false, NoRemoveItems = new List<String>() {
"shortname.example"
}
, CooldownRemove = new CooldownController() {
UseCooldown = false, SecondCooldown = 30,
}
, TemporaryBlockBuildRemove = new RemovePreset.BlockRemoveBuilding() {
UseBlock = false, TimeRemove = 600, PermissionTime = new Dictionary<String, Int32>() {
["iqgraderemove.elite"]
= 100, ["iqgraderemove.vip"] = 300,
}
}
, FullBlockBuildRemove = new RemovePreset.BlockRemoveBuilding() {
UseBlock = false, TimeRemove = 600, PermissionTime = new Dictionary<String, Int32>() {
["iqgraderemove.elite"]
= 1500, ["iqgraderemove.vip"] = 1000,
}
}
, ReturnedRemoveSettings = new RemovePreset.ReturnedSettings() {
returnedChildItems = false, ItemsSettings = new RemovePreset.ReturnedSettings.Items {
UseReturnedItem = true, UsePercentHealts = true, PercentReturn = 100, UseDamageReturned = true, ShortnameNoteReturned = new List<String>() {
"shortname.example",
}
}
, BuildingSettings = new RemovePreset.ReturnedSettings.Building() {
UseReturned = true, UsePercentHealts = true, PercentReturn = 100,
}
}
}
}
;
}
[JsonProperty(LanguageEn ? "Allow remote upgrade/remove (just hit with a mallet next to the object) (grant rights)" : "Разрешить дистанционное улучшение/удаление (достаточно просто рядом с объектом ударить киянкой) (выдайте права)")]
public Boolean UseDistanceFunc;
[JsonProperty(LanguageEn ? "Setting Commands for functions" : "Настройка команд для функций")]
public CommandPresets CommandsList = new CommandPresets();
[JsonProperty(LanguageEn ? "Enable support for rights for each element separately (rights are issued separately for each variation)" : "Включить поддержку прав на каждый элемент отдельно (права выдаются отдельно под каждую вариацию)")]
public Boolean IsCheckPermission;
internal class InterfaceController {
internal class TypeElements {
[JsonProperty(LanguageEn ? "Customize the user interface of the active type (wood/stone, etc.)" : "Настройка UI активных типов (дерево/камень и т.д)")]
public Coordinates TypesElements = new Coordinates();
[JsonProperty(LanguageEn ? "Spacing between elements" : "Отступы между элементами")]
public Single OffsetBetweenElements;
[JsonProperty(LanguageEn ? "Element stroke size" : "Размер обводки выбранного элемента")]
public String SizeSelectedElement;
}
[JsonProperty(LanguageEn ? "Setting up timers" : "Настройка таймера")]
public TimerElement TimerElements = new TimerElement();
[JsonProperty(LanguageEn ? "Setting the 'All' element" : "Настройка элемента 'All'")]
public AllObjects AllObject = new AllObjects();
[JsonProperty(LanguageEn ? "Enable the `Close UI` button (Don't forget to add its image)" : "Включить кнопку `Закрытия UI` (Не забудьте добавить ее изображение)")]
public Boolean closeUIUsed;
internal class TimerElement {
[JsonProperty(LanguageEn ? "Setting the timer position" : "Настройка расположения таймера")]
public Coordinates TimerPosition = new Coordinates();
[JsonProperty(LanguageEn ? "Timer text size" : "Размер текста таймера")]
public Int32 SizeTimer;
}
internal class Coordinates {
public String AnchorMin;
public String AnchorMax;
public String OffsetMin;
public String OffsetMax;
}
[JsonProperty(LanguageEn ? "Setting up the main panel UI" : "Настройка UI главной панели")]
public Coordinates StaticPanel = new Coordinates();
[JsonProperty(LanguageEn ? "Setting up controls" : "Настройка элементов управления")]
public TypeElements TypeElement = new TypeElements();
internal class AllObjects {
[JsonProperty(LanguageEn ? "Setting up the 'All' button" : "Настройка кнопки 'All'")]
public Coordinates AllObjectsButton = new Coordinates();
[JsonProperty(LanguageEn ? "Buttonn stroke size" : "Размер обводки кнопки")]
public String SizeSelectedElement;
}
}
internal class UpgradePreset {
[JsonProperty(LanguageEn ? "Allow upgrade remove after recent damage" : "Разрешить улучшение постройки после недавно нанесенного урона")]
public Boolean UpgradeSecondsAttacks;
[JsonProperty(LanguageEn ? "Require the structure to be repaired before upgrading it if it does not have full durability" : "Требовать починить строение перед его улучшением, если у строения не полное количество прочности")]
public Boolean RepairToGrade;
[JsonProperty(LanguageEn ? "Require authorization in the cupboard before improving the building" : "Требовать авторизацию в шкафу перед улучшением постройки")]
public Boolean NoGradeWithoutCupboard;
[JsonProperty(LanguageEn ? "Disable upgrade during raid block" : "Запретить улучшение во время рейдблока")]
public Boolean NoGradeRaidBlock;
[JsonProperty(LanguageEn ? "Allow rolling back upgrade-level (Example : stone to wood)" : "Разрешить откатывать улучшение назад (Например : камень в дерево)")]
public Boolean BackUpgrade;
[JsonProperty(LanguageEn ? "Return resources when rolling back an upgrade (if metal - into wood - N% of metal resources will be returned)" : "Возвращать ресурсы при откате улучшения назад (если металл - в дерево - будет возвращен N% ресурсов металла)")]
public Boolean BackUpgradeReturnedItem;
[JsonProperty(LanguageEn ? "Indicate the percentage of resource return when rolling back the upgrade" : "Укажите % возврата ресурсов при откате улучшения")]
public Int32 BackUpgradeReturnedItemPercent;
[JsonProperty(LanguageEn ? "Cooldown settings before upgrade a new object" : "Настройка перезарядки перед улучшением нового объекта")]
public CooldownController CooldownUpgrade = new CooldownController();
}
[JsonProperty(LanguageEn ? "Remove the UI when the player has passed all stages of improvement - or will be looped (there will be no looping if the player does not have rights to a particular element with the support of rights to elements enabled)" : "Удалять интерфейс когда игрок пройдет все этапы улучшения - либо будет зациклено (зацикливание не будет если у игрока нет прав на тот или иной элемент при включенной поддержке прав на элементы)")]
public Boolean ConfigResetInterface;
}
private void DrawUI_StaticPanel(BasePlayer player) {
if (_interface == null) return;
CuiHelper.DestroyUi(player, InterfaceBuilder.UI_GREADE_REMOVE_OVERLAY);
String Interface = InterfaceBuilder.GetInterface("UI_Static_Panel");
if (Interface == null) return;
CuiHelper.AddUi(player, Interface);
LocalRepositoryUser localRepositoryUser = LocalRepository[player];
for (Int32 i = 1; i < 6; i++) DrawUI_Types(player, i, localRepositoryUser);
if (_.permission.UserHasPermission(player.UserIDString, PermissionsAllObjects)) DrawUI_Button_AllObject(player, localRepositoryUser.IsAllObjects(player));
}
private enum TypeBlock {
Temporary, Full,
}
object OnPayForUpgrade(BasePlayer player, BuildingBlock block, ConstructionGrade gradeTarget) {
if (permission.UserHasPermission(player.UserIDString, PermissionGRNoResource)) return false;
return null;
}
private class LocalRepositoryUser {
private Boolean isReset;
public Int32 activityTime = 0;
private Boolean isAllObject = false;
private Timer timerInfo;
public ActionType selectedType = ActionType.None;
private Double CooldownUpgrade;
private Double CooldownRemove;
private Boolean UseCooldown() {
return selectedType switch {
ActionType.None => false, ActionType.Remove => config.RemovePresets.CooldownRemove.UseCooldown, _ => config.UpgradePresets.CooldownUpgrade.UseCooldown
}
;
}
public void SetupCooldownData() {
switch (selectedType) {
case ActionType.None : return;
case ActionType.Remove : CooldownRemove = CurrentTime + config.RemovePresets.CooldownRemove.SecondCooldown;
break;
case ActionType.Wood : case ActionType.Stone : case ActionType.Metal : case ActionType.Hqm : default : CooldownUpgrade = CurrentTime + config.UpgradePresets.CooldownUpgrade.SecondCooldown;
break;
}
}
public Boolean IsCooldown() {
if (!UseCooldown()) return false;
Double remainingCooldown = (selectedType == ActionType.Remove) ? CooldownRemove - CurrentTime : CooldownUpgrade - CurrentTime;
return remainingCooldown > 0;
}
public Double GetCooldownTime() {
if (!UseCooldown()) return 0;
if (!IsCooldown()) {
SetupCooldownData();
return 0;
}
if (selectedType == ActionType.Remove) return CooldownRemove - CurrentTime;
return CooldownUpgrade - CurrentTime;
}
public Boolean HasAllObjectsPermission(BasePlayer player) => _.permission.UserHasPermission(player.UserIDString, PermissionsAllObjects);
public Boolean IsAllObjects(BasePlayer player) => HasAllObjectsPermission(player) && isAllObject && selectedType != ActionType.None;
public void TurnedAllObjects(BasePlayer player) {
isAllObject = !isAllObject;
_.DrawUI_Button_AllObject(player, IsAllObjects(player));
}
public Int32 GetGradeLevel => selectedType is ActionType.Remove or ActionType.None ? -1 : (Int32)selectedType;
public void ActionAssignment(BasePlayer player, Int32 customType = -1) {
Int32 correctedCustomType = customType is > 5 or < 1 ? 1 : customType;
Int32 nextTypeAsInt = (customType != -1) ? correctedCustomType : (Int32)selectedType + 1;
if (customType != -1) {
if (!isReset && (Int32)selectedType == nextTypeAsInt) {
isReset = true;
DeleteTimerUI(player);
return;
}
isReset = false;
}
if (config.IsCheckPermission) {
Boolean anyPermissionFound = false;
Boolean sameTypeFound = false;
Boolean onlyOneTypeAvailable = true;
while (nextTypeAsInt <= (Int32)ActionType.Remove) {
if (HasPermissionTypes(player, nextTypeAsInt)) {
anyPermissionFound = true;
if (nextTypeAsInt != (Int32)selectedType) onlyOneTypeAvailable = false;
else sameTypeFound = true;
break;
}
nextTypeAsInt++;
}
if (onlyOneTypeAvailable) {
if (sameTypeFound && timerInfo is {
Destroyed : false
}
) {
isReset = true;
DeleteTimerUI(player);
return;
}
if (!anyPermissionFound && (timerInfo == null || timerInfo.Destroyed)) {
_.MessageGameTipsError(player, _.GetLang("NO_PERMISSION", player.UserIDString));
return;
}
DeleteTimerUI(player);
return;
}
}
if (nextTypeAsInt > (Int32)ActionType.Remove) {
if (isReset || !config.ConfigResetInterface) {
nextTypeAsInt = (Int32)ActionType.Wood;
isReset = false;
}
else {
isReset = true;
DeleteTimerUI(player);
return;
}
}
selectedType = (ActionType)nextTypeAsInt;
_.DrawUI_StaticPanel(player);
ResetTimer(player);
}
public Boolean HasPermissionTypes(BasePlayer player, Int32 actionType) {
if (!config.IsCheckPermission) return true;
return actionType switch {
(Int32)ActionType.Wood => _.permission.UserHasPermission(player.UserIDString, PermissionsUpWood), (Int32)ActionType.Stone => _.permission.UserHasPermission(player.UserIDString, PermissionsUpStone), (Int32)ActionType.Metal => _.permission.UserHasPermission(player.UserIDString, PermissionsUpMetal), (Int32)ActionType.Hqm => _.permission.UserHasPermission(player.UserIDString, PermissionsUpHqm), (Int32)ActionType.Remove => _.permission.UserHasPermission(player.UserIDString, PermissionsRemove), _ => false
}
;
}
public void ResetTimer(BasePlayer player) {
timerInfo?.Destroy();
activityTime = (Int32)CurrentTime + config.ConfigActiveGradeRemove;
_.DrawUI_Timer(player, (Int32)(activityTime - CurrentTime));
timerInfo = _.timer.Repeat(1f, config.ConfigActiveGradeRemove, () => {
TimerController(player);
}
);
}
private void TimerController(BasePlayer player) {
if (CurrentTime >= activityTime) DeleteTimerUI(player);
else _.DrawUI_Timer_Update(player, (Int32)(activityTime - CurrentTime));
}
public void DeleteTimerUI(BasePlayer player) {
CuiHelper.DestroyUi(player, InterfaceBuilder.UI_GREADE_REMOVE_OVERLAY);
timerInfo?.Destroy();
selectedType = ActionType.None;
}
}
private Boolean HandleItemReturn(BasePlayer player, BaseEntity entity, String NormalizePrefab, Configuration.RemovePreset.ReturnedSettings.Items ItemsSettings) {
if (entity is BuildingBlock) return false;
Item ItemReturned = CreateItem(entity, NormalizePrefab);
if (ItemsSettings.UseReturnedItem && ItemReturned != null) {
if (ItemsSettings.UseDamageReturned && entity is BaseCombatEntity combatEntity) {
Single healthFraction = combatEntity.health / entity.MaxHealth();
ItemReturned.conditionNormalized = Mathf.Clamp01(healthFraction - combatEntity.pickup.subtractCondition);
}
HandleItemChildReturn(entity, player, ItemsSettings);
player.GiveItem(ItemReturned);
return true;
}
else if (entity is BaseCombatEntity combatEntity) {
ItemDefinition itemDef = ItemManager.FindItemDefinition(ItemReturned.info.shortname);
if (itemDef == null || itemDef.Blueprint == null || itemDef.Blueprint.ingredients == null) {
HandleItemChildReturn(entity, player, ItemsSettings);
player.GiveItem(ItemReturned);
return true;
}
Single PercentReturnResource = ItemsSettings.UsePercentHealts ? combatEntity.health / combatEntity.MaxHealth() : ItemsSettings.PercentReturn / 100.0f;
foreach (ItemAmount CostReturned in itemDef.Blueprint.ingredients) {
Int32 Amount = Mathf.FloorToInt(CostReturned.amount * PercentReturnResource);
if (Amount <= 0 && CostReturned.amount == 1) {
if (UnityEngine.Random.value > 0.5f) Amount = 1;
else continue;
}
HandleItemChildReturn(entity, player, ItemsSettings);
player.GiveItem(ItemManager.Create(CostReturned.itemDef, Amount));
}
return true;
}
if (IQRecycler?.Call<Boolean>("API_IsValidRecycler", entity) != true) return false;
Item RecyclerReturned = IQRecycler.Call<Item>("API_GetItemRecyclerAfterRemove", entity, player);
player.GiveItem(RecyclerReturned);
return true;
}
Int32 API_GET_GRADE_LEVEL_PLAYER(BasePlayer player) {
if (player == null) return 0;
if (!LocalRepository.ContainsKey(player)) return 0;
return (Int32)LocalRepository[player].selectedType;
}
private Int32 GetFilteredCollidersCount(Collider[] colliders, int count) {
return colliders.Take(count).Count(x => x.name.Contains("assets") && !x.name.Contains("building") && !x.name.Contains("player"));
}
void ReadData() {
TemporaryBlockBuild = Oxide.Core.Interface.Oxide.DataFileSystem.ReadObject<Dictionary<UInt64, Double>>("IQSystem/IQGradeRemove/TemporaryBlockBuilding");
FullBlockBuild = Oxide.Core.Interface.Oxide.DataFileSystem.ReadObject<Dictionary<UInt64, Double>>("IQSystem/IQGradeRemove/FullBlockBuilding");
}
private void SetupBlockBuild(String userID, TypeBlock typeBlock, UInt64 buildNetID) {
Dictionary<UInt64, Double> BlockList = typeBlock == TypeBlock.Temporary ? TemporaryBlockBuild : FullBlockBuild;
if (!BlockList.ContainsKey(buildNetID)) BlockList[buildNetID] = GetTimeBlock(userID, typeBlock);
}
private void OnServerInitialized() {
if (AutoBaseUpgrade && AutoBaseUpgrade.Version < new VersionNumber(1, 2, 2)) {
NextTick(() => {
PrintError(LanguageEn ? "You have an outdated version of AutoBaseUpgrade installed.Please update to version 1.2.2 or higher" : "У вас установлена устаревшая версия AutoBaseUpgrade, обновитесь до версии выше 1.2.2");
Interface.Oxide.UnloadPlugin(Name);
}
);
}
if (config.CommandsList.UpgradeCommands.Count == 0) {
PrintWarning(LanguageEn ? "You don't have upgrade commands, the plugin can't work" : "У вас не указаны команды для улучшения, плагин не может работать");
Interface.Oxide.UnloadPlugin(Name);
return;
}
if (config.CommandsList.UpgradeCommands.Count == 0) {
PrintWarning(LanguageEn ? "You don't have remove commands, the plugin can't work" : "У вас не указаны команды для удаления, плагин не может работать");
Interface.Oxide.UnloadPlugin(Name);
return;
}
_imageUI = new ImageUI();
_imageUI.DownloadImage();
if (!config.UseDistanceFunc) Unsubscribe("OnPlayerInput");
RegisteredPermissions();
foreach (String upgradeCommand in config.CommandsList.UpgradeCommands) {
cmd.AddChatCommand(upgradeCommand, this, nameof(ChatCMDUp));
cmd.AddConsoleCommand(upgradeCommand, this, nameof(ConsoleCMDUp));
}
foreach (String removeCommand in config.CommandsList.RemoveCommands) {
cmd.AddChatCommand(removeCommand, this, nameof(ChatCMDRemove));
cmd.AddConsoleCommand(removeCommand, this, nameof(ConsoleCMDRemove));
}
foreach (BasePlayer player in BasePlayer.activePlayerList) OnPlayerConnected(player);
}
private Boolean CheckNearbyCollider(BuildingBlock block) {
Collider[] colliders = new Collider[30];
Int32 colliderCount = Physics.OverlapSphereNonAlloc(block.CenterPoint() + new Vector3(0f, 0f, 0f), 2f, colliders);
Int32 FilteredCountFloor = GetFilteredCollidersCount(colliders, colliderCount);
return FilteredCountFloor < 1;
}
private Dictionary<BasePlayer, LocalRepositoryUser> LocalRepository = new Dictionary<BasePlayer, LocalRepositoryUser>();
private String CanUpgrade(BasePlayer player, BuildingBlock buildingBlock, LocalRepositoryUser repositoryUser, BuildingGrade.Enum grade = BuildingGrade.Enum.None) {
if (buildingBlock.name.Contains("foundation") && DeployVolume.Check(buildingBlock.transform.position, buildingBlock.transform.rotation, PrefabAttribute.server.FindAll<DeployVolume>(buildingBlock.prefabID), ~(1 << buildingBlock.gameObject.layer))) return GetLang("UPGRADE_FOREIGN_OBJECT", player.UserIDString);
if (!config.UpgradePresets.UpgradeSecondsAttacks && buildingBlock.SecondsSinceAttacked < 30) return GetLang("UPGRADE_SINCE_ATTACKED_BLOCK", player.UserIDString, FormatTime(TimeSpan.FromSeconds(30 - (Int32)buildingBlock.SecondsSinceAttacked), player.UserIDString));
if(config.UpgradePresets.NoGradeWithoutCupboard) if (player.GetBuildingPrivilege() == null || !player.IsBuildingAuthed()) return GetLang("UPGRADE_NO_AUTH_BUILDING_CUPBOARD", player.UserIDString);
if (!player.CanBuild()) return GetLang("UPGRADE_NO_AUTH_BUILDING", player.UserIDString);
Double CooldownTime = repositoryUser.GetCooldownTime();
if (CooldownTime > 0) return GetLang("UPGRADE_TIME_EXECURE", player.UserIDString, FormatTime(TimeSpan.FromSeconds(CooldownTime), player.UserIDString));
if (config.UpgradePresets.NoGradeRaidBlock && IsRaidBlocked(player)) return GetLang("UPGRADE_NO_ESCAPE", player.UserIDString);
if (config.UpgradePresets.RepairToGrade && buildingBlock.health < buildingBlock.MaxHealth() && buildingBlock.grade != BuildingGrade.Enum.Twigs) return GetLang("UPGRADE_REPAIR_OBJECTS", player.UserIDString);
if (permission.UserHasPermission(player.UserIDString, PermissionGRNoResource)) return String.Empty;
Int32 gradeLevel = grade == BuildingGrade.Enum.None ? repositoryUser.GetGradeLevel : (Int32)grade;
return !buildingBlock.CanAffordUpgrade((BuildingGrade.Enum)gradeLevel, 0, player) ? GetLang("UPGRADE_NOT_ENOUGHT_RESOURCE", player.UserIDString) : String.Empty;
}
[ConsoleCommand("upgrade.func")]
private void UpgradeFuncCMD(ConsoleSystem.Arg arg) {
BasePlayer player = arg.Player();
if (player == null) return;
LocalRepository[player].ActionAssignment(player, Convert.ToInt32(arg.Args[0]));
}
private String GetLang(String LangKey, String userID = null, params Object[] args) {
// ... [Code preview truncated due to length. Full source in attached file] ...