C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Oxide.Core.Libraries;
using Oxide.Core;
using System.Collections;
using System.Globalization;
using UnityEngine.Networking;
using Time = UnityEngine.Time;
using System.Text;
using ConVar;
using Rust;
using VLB;
using System.Collections.Generic;
using Layer = Rust.Layer;
using Oxide.Plugins.RaidBlockExt;
using UnityEngine;
using Pool = Facepunch.Pool;
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using System.Linq;
using Oxide.Game.Rust.Cui;
using System;
namespace Oxide.Plugins {
[Info("RaidBlock", "DezLife & Mercury", "1.3.5")]
public class RaidBlock : RustPlugin {
private const string RB_WHITE_AND_BLACK_LIST_ITEM = "toolgun";
private const string VISUALIZATION_BR_SPHERE_PREFAB_GREEN = "assets/bundled/prefabs/modding/events/twitch/br_sphere_green.prefab";
private const ulong RB_BLACKLIST_ITEM_SKIN = 3100653751;
private bool IsRaidBlock(ulong userId) => IsRaidBlocked(userId);
private bool FindItemInInventory(BasePlayer player, ulong skinId) {
List<Item> items = Pool.Get<List<Item>>();
try {
player.inventory.GetAllItems(items);
return items.Any(item => item.skin == skinId);
}
finally {
Pool.Free(ref items);
}
}
private bool IsRaidDamage (DamageType dt) => config.BlockDetect.RaidBlockOnTakeDamageHook._damageTypes.Contains(dt);
private object OnHammerHit(BasePlayer player, HitInfo info) {
if (player == null || info is null) return null;
if (player.GetActiveItem() is not {
}
activeItem) return null;
if (!activeItem.info.shortname.Equals(RB_WHITE_AND_BLACK_LIST_ITEM) || (activeItem.skin is not RB_WHITELIST_ITEM_SKIN and not RB_BLACKLIST_ITEM_SKIN)) return null;
if (!HasPermission(player)) return null;
UpdateWhiteOrBlackList(player, activeItem.skin, info);
return false;
}
private class RaidPlayer : FacepunchBehaviour {
public BasePlayer player;
public float blockEnds;
public float UnblockTimeLeft => Convert.ToInt32(blockEnds - Time.realtimeSinceStartup);
private void Awake() {
player = GetComponent<BasePlayer>();
if(!Instance.raidPlayersList.Contains(this)) Instance.raidPlayersList.Add(this);
Interface.CallHook("OnRaidBlockStarted", player);
}
public void Kill(bool force = false) {
if (!force) {
if (Instance.raidPlayersList.Contains(this)) Instance.raidPlayersList.Remove(this);
}
DestroyImmediate(this);
}
private void OnDestroy() {
CuiHelper.DestroyUi(player, InterfaceBuilder.RB_MAIN);
Interface.CallHook("OnRaidBlockStopped", player);
}
public void UpdateTime(float time, bool customTime = false) {
if (customTime) {
blockEnds = time;
return;
}
if (time > blockEnds) blockEnds = time;
}
public void ActivateBlock(float time) {
if(time > blockEnds) blockEnds = time;
CrateUI();
InvokeRepeating(CheckTimeLeft, 0, 1);
}
private void CheckTimeLeft() {
if (UnblockTimeLeft > 0) {
RefreshUI();
}
else {
CuiHelper.DestroyUi(player, InterfaceBuilder.RB_MAIN);
CancelInvoke(nameof(CheckTimeLeft));
Kill();
}
}
public void CrateUI() => Instance.DrawUI_RB_Main(player, UnblockTimeLeft);
private void RefreshUI() => Instance.DrawUI_RB_Updated(player, UnblockTimeLeft);
}
private List<BasePlayer> playerInCache = new();
private bool IsBlockedClass(BaseCombatEntity entity) => entity is BuildingBlock or Door or SimpleBuildingBlock or Workbench or Barricade or BasePlayer;
private bool IsBlackList(BaseCombatEntity entity) {
return config.BlockDetect.RbBlackList.Any(blackEnt => entity.prefabID == blackEnt);
}
private object canTrade(BasePlayer player) => CanTrade(player);
private static string GetGridString(Vector3 position) => MapHelper.PositionToString(position);
private const string VENDING_MAP_MARKER_PREFAB = "assets/prefabs/deployable/vendingmachine/vending_mapmarker.prefab";
private bool CheckEntity(BaseCombatEntity entity, HitInfo info, BasePlayer raider) {
if (entity.OwnerID == 0 || !entity.OwnerID.IsSteamId()) return false;
if (config.BlockDetect.IgnoreEntsHealth > 0 && entity.MaxHealth() < config.BlockDetect.IgnoreEntsHealth) return false;
if (entity is BuildingBlock {
grade : BuildingGrade.Enum.Twigs
}
block) return false;
if (raider != null && config.BlockDetect.RaidYourself == false) {
if (raider.userID == entity.OwnerID) return false;
if (IsFriends(raider, entity.OwnerID)) return false;
}
return true;
}
[ChatCommand("rbtest")]
void rbtest(BasePlayer player) {
if(!player.IsAdmin) return;
CreateOrRefreshRaidblock(player.transform.position, player);
}
private List<ulong> GetFriendList(BasePlayer targetPlayer) {
List<ulong> friendList = Pool.Get<List<ulong>>();
if (Friends) {
if (Friends.Call("GetFriends", targetPlayer.userID.Get()) is ulong[] friends) friendList.AddRange(friends);
}
if (Clans) {
if (Clans.Call("GetClanMembers", targetPlayer.UserIDString) is ulong[] clanMembers) friendList.AddRange(clanMembers);
}
if (targetPlayer.Team != null) friendList.AddRange(targetPlayer.Team.members);
return friendList;
}
private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
if (info == null || entity == null) return;
DamageType majorityDamageType = info.damageTypes.GetMajorityDamageType();
if (majorityDamageType == DamageType.Decay) return;
if (!IsRaidDamage(info.damageTypes)) return;
BasePlayer raider = info.InitiatorPlayer != null ? info.InitiatorPlayer : entity.lastAttacker as BasePlayer;
if (raider == null) return;
Configuration.RaidBlockDetect.RaidBlockOnTakeDamage damageRaidBlock = config.BlockDetect.RaidBlockOnTakeDamageHook;
if (IsRaidBlocked(raider) && !damageRaidBlock.UpdateBlockOnTakeDamage) return;
string shortnameWeapon = string.Empty;
if (info.WeaponPrefab != null) {
if (!_prefabID2Item.TryGetValue(info.WeaponPrefab.prefabID, out shortnameWeapon)) _prefabNameItem.TryGetValue(info.WeaponPrefab.ShortPrefabName, out shortnameWeapon);
}
if (!string.IsNullOrWhiteSpace(shortnameWeapon) && damageRaidBlock.RbOnTakeDamageBlackList.Contains(shortnameWeapon)) return;
if (GetHealthPercent(entity, info.damageTypes.Total()) > config.BlockDetect.RaidBlockOnTakeDamageHook.RbOnTakeDamageMinCondition) return;
OnEntCheck(entity, info);
}
private bool IsBlocked(BasePlayer player) {
RaidPlayer obj = player.GetComponent<RaidPlayer>();
return obj != null && obj.UnblockTimeLeft > 0;
}
private void DrawUI_RB_Main(BasePlayer player, float timeLeft = 0f) {
string Interface = InterfaceBuilder.GetInterface(InterfaceBuilder.RB_MAIN);
if (Interface == null) return;
switch (InterfaceBuilder.TypeUi) {
case 0 : Interface = Interface.Replace("%Descriptions%", "RAIDBLOCK_UI_DESCRIPTIONS_V1".GetAdaptedMessage(player.UserIDString));
break;
case 1 : Interface = Interface.Replace("%Descriptions%", "RAIDBLOCK_UI_DESCRIPTIONS_V2".GetAdaptedMessage(player.UserIDString));
break;
}
Interface = Interface.Replace("%Title%", "RAIDBLOCK_UI_TITLE".GetAdaptedMessage(player.UserIDString));
CuiHelper.DestroyUi(player, InterfaceBuilder.RB_MAIN);
CuiHelper.AddUi(player, Interface);
DrawUI_RB_Updated(player, timeLeft == 0 ? config.RaidBlockMain.RaidBlockDuration : timeLeft, true);
}
private int ApiGetTime(ulong userId) {
if (!IsRaidBlocked(userId.ToString())) return 0;
BasePlayer player = BasePlayer.FindByID(userId);
if (player == null) return 0;
RaidPlayer obj = player.GetComponent<RaidPlayer>();
return obj == null ? 0 : int.Parse(obj.UnblockTimeLeft.ToString(CultureInfo.InvariantCulture));
}
private object CanBuild(Planner planner, Construction prefab, Construction.Target target) {
BasePlayer player = planner.GetOwnerPlayer();
if (player == null) return null;
string shortname = prefab.hierachyName[(prefab.hierachyName.IndexOf("/", StringComparison.Ordinal) + 1)..];
if (config.ActionsBlocked.RbDeployWhiteList.Contains(shortname)) return null;
Deployable deployable = planner.GetDeployable();
if (deployable != null && !config.ActionsBlocked.CanDeployObjects) return null;
if (prefab.defaultGrade != null && !config.ActionsBlocked.CanBuildTwig) return null;
return CanActions(player);
}
private class ImageUI {
private readonly string _paths;
private readonly string _printPath;
private readonly Dictionary<string, ImageData> _images;
private enum ImageStatus {
NotLoaded, Loaded, Failed
}
public ImageUI() {
_paths = Instance.Name + "/Images/";
_printPath = "data/" + _paths;
_images = new Dictionary<string, ImageData> {
{
"RB_FON0", new ImageData()
}
, {
"RB_FON1", new ImageData()
}
, {
"RB_FON2", new ImageData()
}
, {
"RB_VARIANT0_ICON", new ImageData()
}
, {
"RB_VARIANT1_ICON_FON", new ImageData()
}
, {
"RB_VARIANT1_ICON", new ImageData()
}
, {
"RB_VARIANT2_ICON", new ImageData()
}
,
}
;
}
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() {
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);
Instance.PrintError(LanguageEn ? $"Failed to load the following images: {images}.Perhaps you did not upload them to the '{_printPath}' folder." : $"Не удалось загрузить следующие изображения: {images}.Возможно, вы не загрузили их в папку '{_printPath}'.");
Interface.Oxide.UnloadPlugin(Instance.Name);
}
else {
Instance.Puts(LanguageEn ? $"{_images.Count} images downloaded successfully!" : $"{_images.Count} изображений успешно загружено!");
Instance.Puts(LanguageEn ? "Generating the interface, please wait for approximately 5-10 seconds" : "Генерируем интерфейс, ожидайте ~5-10 секунд");
_interface = new InterfaceBuilder();
Instance.Puts(LanguageEn ? "The interface has been successfully loaded" : "Интерфейс успешно загружен!");
}
}
}
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 + "/" + _paths + 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 object canTeleport(BasePlayer player) => CanActions(player);
private static RaidableZone GetRbZone(Vector3 position) {
List<SphereCollider> sphereColliders = Pool.Get<List<SphereCollider>>();
Vis.Colliders(position, 0.1f, sphereColliders);
foreach (SphereCollider sCollider in sphereColliders) {
if (sCollider.gameObject.TryGetComponent(out RaidableZone rbZone)) {
Pool.FreeUnmanaged(ref sphereColliders);
return rbZone;
}
}
Pool.FreeUnmanaged(ref sphereColliders);
return null;
}
private enum SphereTypes {
BlackSphere, BRSphere,
}
object CanBGrade(BasePlayer player, int grade, BuildingBlock buildingBlock, Planner planner) {
RaidPlayer playPlayer = player.GetComponent<RaidPlayer>();
if (playPlayer != null && playPlayer.UnblockTimeLeft > 0) {
RunEffect(player, "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab");
return -1;
}
return null;
}
private void SubscribeHook(bool main, bool raidActions) {
if (main) {
Subscribe(nameof(OnEntityDeath));
Subscribe(nameof(OnPlayerConnected));
if(config.BlockDetect.RaidBlockOnTakeDamageHook.ActivateBlockOnTakeDamage) Subscribe(nameof(OnEntityTakeDamage));
if (config.RaidBlockMain.RaidableBasesIntegration.useRaidableBases) {
if(config.RaidBlockMain.RaidableBasesIntegration.BlockOnEnterZone) Subscribe(nameof(OnPlayerEnteredRaidableBase));
if(config.RaidBlockMain.RaidableBasesIntegration.BlockOnExitZone) Subscribe(nameof(OnPlayerExitedRaidableBase));
}
}
if (raidActions) {
if (config.ActionsBlocked.RbBlackListCommand != null && config.ActionsBlocked.RbBlackListCommand.Count != 0) {
if (config.ActionsBlocked.RbBlackListCommand.Count == 1 && config.ActionsBlocked.RbBlackListCommand[0].Equals("commandExample")) return;
Subscribe(nameof(OnPlayerCommand));
Subscribe(nameof(OnServerCommand));
}
if (config.RaidBlockMain.RaidBlockOnPlayerDeath) {
Subscribe(nameof(OnPlayerDeath));
}
if (config.ActionsBlocked.CanUseKit) {
Subscribe(nameof(CanRedeemKit));
}
if (config.ActionsBlocked.CanUseTeleport) {
Subscribe(nameof(canTeleport));
Subscribe(nameof(CanTeleport));
}
if (config.ActionsBlocked.CanUseTeleportHome) {
Subscribe(nameof(CanTeleportHome));
}
if (config.ActionsBlocked.CanUseTrade) {
Subscribe(nameof(canTrade));
Subscribe(nameof(CanTrade));
}
if (config.ActionsBlocked.CanDemolishObjects) {
Subscribe(nameof(OnStructureDemolish));
Subscribe(nameof(canRemove));
Subscribe(nameof(CanRemove));
}
if (config.ActionsBlocked.CanRepairObjects) {
Subscribe(nameof(OnStructureRepair));
}
if (config.ActionsBlocked.CanBuildTwig || config.ActionsBlocked.CanDeployObjects || config.ActionsBlocked.RbDeployWhiteList.Count > 0) {
Subscribe(nameof(CanBuild));
}
if (config.ActionsBlocked.CanUseBGrade) {
Subscribe(nameof(CanBGrade));
}
if (config.ActionsBlocked.CanUpgradeObjects) {
Subscribe(nameof(OnStructureUpgrade));
Subscribe(nameof(OnStructureRotate));
}
if (config.ActionsBlocked.CanPickUpObjects) {
Subscribe(nameof(CanPickupEntity));
}
}
}
private object OnPlayerCommand(BasePlayer player, string command, string[] args) {
if (player == null) return null;
if (args != null && args.Length != 0) command += " " + string.Join(" ", args);
string onlyCommand = !string.IsNullOrWhiteSpace(command) && command.Contains(" ") ? command.Substring(0, command.IndexOf(" ", StringComparison.Ordinal)) : command;
return config.ActionsBlocked.RbBlackListCommand.Contains(onlyCommand.ToLower()) ? CanActions(player) : null;
}
private const string VISUALIZATION_SPHERE_PREFAB = "assets/prefabs/visualization/sphere.prefab";
private object CanTeleport(BasePlayer player) => CanActions(player, true);
private RaidPlayer GetRaidPlayer(BasePlayer player) {
RaidPlayer obj = player.GetComponent<RaidPlayer>();
return obj;
}
private readonly string _permIgnoreRaid = ".ignore";
private object CanTeleportHome(BasePlayer player, Vector3 to) {
RaidableZone isRbZone = GetRbZone(to);
if (isRbZone != null) {
RunEffect(player, "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab");
return "RAIDBLOCK_ACTION_BLOCKED_ZONE".GetAdaptedMessage(player.UserIDString, isRbZone.UnblockTimeLeft.ToTimeFormat());
}
return null;
}
private const string VISUALIZATION_BR_SPHERE_PREFAB_BLUE = "assets/bundled/prefabs/modding/events/twitch/br_sphere.prefab";
private object OnStructureDemolish(BaseCombatEntity entity, BasePlayer player, bool immediate) => CanActions(player);
private void UpdateWhiteOrBlackList(BasePlayer player, ulong skinId, HitInfo info) {
BaseEntity entity = info.HitEntity;
if (entity == null) return;
uint prefabId = entity.prefabID;
HashSet<uint> listToUpdate = skinId switch {
RB_WHITELIST_ITEM_SKIN => config.BlockDetect.RbWhiteList, RB_BLACKLIST_ITEM_SKIN => config.BlockDetect.RbBlackList, _ => null
}
;
if (listToUpdate == null) return;
string messageKey = UpdateList(listToUpdate, prefabId) ? skinId == RB_WHITELIST_ITEM_SKIN ? "RAIDBLOCK_TOOLGUN_ADDED_TO_WHITELIST" : "RAIDBLOCK_TOOLGUN_ADDED_TO_BLACKLIST" : skinId == RB_WHITELIST_ITEM_SKIN ? "RAIDBLOCK_TOOLGUN_REMOVED_FROM_WHITELIST" : "RAIDBLOCK_TOOLGUN_REMOVED_FROM_BLACKLIST";
GameTipsSendPlayer(player, messageKey.GetAdaptedMessage(player.UserIDString, entity.ShortPrefabName, prefabId));
SaveConfig();
return;
bool UpdateList(HashSet<uint> list, uint id) {
if (!list.Add(id)) {
list.Remove(id);
return false;
}
return true;
}
}
private static InterfaceBuilder _interface;
private object OnServerCommand(ConsoleSystem.Arg arg) {
BasePlayer player = arg.Player();
if (player == null || arg.cmd.FullName == "chat.say") return null;
string command = arg.cmd.Name;
if (arg.Args != null && arg.Args.Length != 0) command += " " + string.Join(" ", arg.Args);
string onlyCommand = !string.IsNullOrWhiteSpace(command) && command.Contains(" ") ? command.Substring(0, command.IndexOf(" ", StringComparison.Ordinal)) : command;
return config.ActionsBlocked.RbBlackListCommand.Contains(onlyCommand.ToLower()) ? CanActions(player) : null;
}
private bool HasPermission(BasePlayer player) {
if (!permission.UserHasPermission(player.UserIDString, Name + _permHelperToolGun) && !player.IsAdmin) {
SendChat("RAIDBLOCK_TOOLGUN_PERMISSION_DENIED".GetAdaptedMessage(player.UserIDString), player);
return false;
}
return true;
}
private void UnsubscribeHook(bool main, bool raidActions) {
if (main) {
Unsubscribe(nameof(OnEntityDeath));
Unsubscribe(nameof(OnEntityTakeDamage));
Unsubscribe(nameof(OnPlayerConnected));
Unsubscribe(nameof(OnPlayerEnteredRaidableBase));
Unsubscribe(nameof(OnPlayerExitedRaidableBase));
}
if (raidActions) {
Unsubscribe(nameof(OnPlayerDeath));
Unsubscribe(nameof(CanBGrade));
Unsubscribe(nameof(CanBuild));
Unsubscribe(nameof(OnStructureUpgrade));
Unsubscribe(nameof(OnStructureRepair));
Unsubscribe(nameof(OnStructureDemolish));
Unsubscribe(nameof(OnStructureRotate));
Unsubscribe(nameof(canTeleport));
Unsubscribe(nameof(CanTeleport));
Unsubscribe(nameof(CanTeleportHome));
Unsubscribe(nameof(OnPlayerCommand));
Unsubscribe(nameof(OnServerCommand));
Unsubscribe(nameof(canRemove));
Unsubscribe(nameof(CanRemove));
Unsubscribe(nameof(canTrade));
Unsubscribe(nameof(CanTrade));
Unsubscribe(nameof(CanRedeemKit));
Unsubscribe(nameof(CanPickupEntity));
}
}
private bool IsRaidBlocked(ulong playerId) {
BasePlayer target = BasePlayer.Find(playerId.ToString());
return target != null && IsBlocked(target);
}
private class Configuration {
public class RaidBlockActionsBlocked {
[JsonProperty(LanguageEn ? "Forbid building repair" : "Запретить починку строений")]
public bool CanRepairObjects = true;
[JsonProperty(LanguageEn ? "Forbid picking up items (furnaces, boxes, etc.)" : "Запретить поднятие вещей (печки/ящики и т.д)")]
public bool CanPickUpObjects = false;
[JsonProperty(LanguageEn ? "Forbid upgrading buildings" : "Запретить улучшение строений")]
public bool CanUpgradeObjects = true;
[JsonProperty(LanguageEn ? "Forbid building removal" : "Запретить удаление строений")]
public bool CanDemolishObjects = true;
[JsonProperty(LanguageEn ? "Forbid teleportation" : "Запретить телепортацию")]
public bool CanUseTeleport = true;
[JsonProperty(LanguageEn ? "Forbid teleporting home if he is within the radius of the raid block" : "Запретить телепортироваться домой, если он в радиусе рейдблока")]
public bool CanUseTeleportHome = true;
[JsonProperty(LanguageEn ? "Forbid the use of BGrade" : "Запретить использования BGrade")]
public bool CanUseBGrade = true;
[JsonProperty(LanguageEn ? "Forbid the use of kits" : "Запретить использование китов")]
public bool CanUseKit = true;
[JsonProperty(LanguageEn ? "Forbid the use of trade" : "Запретить использование обмена (Trade)")]
public bool CanUseTrade = true;
[JsonProperty(LanguageEn ? "Forbid building" : "Запретить строение")]
public bool CanBuildTwig = true;
[JsonProperty(LanguageEn ? "Forbid object placement (furnaces, boxes, etc.)" : "Запретить размещение объектов (Печки, ящики и другое)")]
public bool CanDeployObjects = false;
[JsonProperty(LanguageEn ? "List of objects allowed to build/place during the raidblock (shortname)" : "Список объектов, которые разрешено строить/размещать во время рейдблока (PrefabName)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> RbDeployWhiteList = new() {
"bed_deployed", "ladder.wooden.wall",
}
;
[JsonProperty(LanguageEn ? "List of prohibited commands when blocking is active [specify them without a slash (/) in lower case]" : "Список запрещенных команд при активной блокировки [указывайте их без слэша (/) в нижнем регистре]", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> RbBlackListCommand = new() {
"commandexample",
}
;
}
[JsonProperty(LanguageEn ? "Interface settings" : "Настройки интерфейса")]
public RaidBlockUi RaidBlockInterface = new();
[JsonProperty(LanguageEn ? "Setting up triggers for the raidblock" : "Настройка триггеров для рейдблока")]
public RaidBlockDetect BlockDetect = new();
public class RaidableBases {
[JsonProperty(LanguageEn ? "RaidableBases: Enable support for Raidable Bases?" : "RaidableBases : Включить поддержку Raidable Bases ?")]
public bool useRaidableBases = false;
[JsonProperty(LanguageEn ? "RaidableBases: Blocking time (Seconds)" : "RaidableBases: Время блокировки (Секунды)")]
public int RaidBlockDuration = 600;
[JsonProperty(LanguageEn ? "RaidableBases : Give a raid block when entering the Raidable Bases zone" : "RaidableBases : Давать рейд блок при входе в зону Raidable Bases")]
public bool BlockOnEnterZone = false;
[JsonProperty(LanguageEn ? "RaidableBases : Remove the raid block when leaving the Raidable Bases zone" : "RaidableBases : Снимать рейд блок при выходе из зоны Raidable Bases")]
public bool BlockOnExitZone = false;
}
[JsonProperty(LanguageEn ? "Setting restrictions during the raid block" : "Настройка ограничений во время рейдблока")]
public RaidBlockActionsBlocked ActionsBlocked = new();
public class RaidBlock {
[JsonProperty(LanguageEn ? "Radius of blocking zone (Meters)" : "Радиус зоны блокировки (Метры)")]
public int RaidBlockDistance = 130;
[JsonProperty(LanguageEn ? "Blocking time (Seconds)" : "Время блокировки (Секунды)")]
public int RaidBlockDuration = 300;
[JsonProperty(LanguageEn ? "Use dynamic raid zone (shift the zone center to the explosion location)" : "Использовать динамичную зону рейда (смещение центра зоны к месту взрыва)")]
public bool IsDynamicRaidZone = false;
[JsonProperty(LanguageEn ? "Spread raidblock to all team players" : "Распространять рейд блок на всех игроков в команде инициатора рейда")]
public bool RaidBlockShareOnFriends = true;
[JsonProperty(LanguageEn ? "When entering the active raid block zone, activate the player raid block" : "При входе в активную зону рейдблока - активировать рейдблок игроку")]
public bool RaidBlockOnEnterRaidZone = true;
[JsonProperty(LanguageEn ? "Upon exiting the raid block zone, deactivate the raid block for the player" : "При выходе из зоны рейдблока - деактивировать рейдблок игроку")]
public bool RaidBlockOnExitRaidZone = false;
[JsonProperty(LanguageEn ? "When exiting the raid block zone, leave a lock for N seconds (leave 0 if you don't need it)" : "При выходе из зоны рейдблока - оставлять N секунд блокировки (оставьте 0 - если вам не нужно это)")]
public Int32 TimeLeftOnExitZone = 0;
[JsonProperty(LanguageEn ? "Activate raid block for all players within the effective radius after the raid starts" : "Активировать рейдблок для всех игроков в радиусе действия после начала рейда")]
public bool RaidBlockAddedAllPlayersInZoneRaid = true;
[JsonProperty(LanguageEn ? "Deactivate the raid block for the player upon death" : "Деактивировать рейдблок игроку после смерти")]
public bool RaidBlockOnPlayerDeath = true;
[JsonProperty(LanguageEn ? "Raid zone map marker settings" : "Настройки маркера на карте в зоне рейда")]
public MapMarkerSettings mapMarkerSettings = new();
[JsonProperty(LanguageEn ? "Visual raid zone (Dome) settings" : "Настройка визуальной зоны рейда (купол)")]
public SphereSettings RaidZoneSphereSettings = new();
[JsonProperty(LanguageEn ? "Integration settings with RaidableBases" : "Настройки интеграции с RaidableBases")]
public RaidableBases RaidableBasesIntegration = new();
public class SphereSettings {
[JsonProperty(LanguageEn ? "Activate visual raid zone (Dome)" : "Активировать визуальную зону рейда (купол)")]
public bool IsSphereEnabled = false;
[JsonProperty(LanguageEn ? "Choose marker type: 0 - standard dome, 1 - BattleRoyale dome" : "Выберете тип купола : 0 - cтандартный купол, 1 - BattleRoyale купол")]
public SphereTypes SphereType = SphereTypes.BlackSphere;
[JsonProperty(LanguageEn ? "Color for BattleRoyale dome: 0 - blue | 1 - green | 2 - purple | 3 - red" : "Цвет для BattleRoyale купола : 0 - blue | 1 - green | 2 - purple | 3 - red")]
public BRZoneColor BRZoneColor = BRZoneColor.Blue;
[JsonProperty(LanguageEn ? "Transparency level of the standard dome (Lower values mean more transparency.The value should not exceed 5)" : "Уровень прозрачности стандартного купола (Чем меньше - тем прозрачнее.Значения должно быть не более 5)")]
public int DomeTransparencyLevel = 3;
public string GetBRZonePrefab() {
return BRZoneColor switch {
BRZoneColor.Blue => VISUALIZATION_BR_SPHERE_PREFAB_BLUE, BRZoneColor.Green => VISUALIZATION_BR_SPHERE_PREFAB_GREEN, BRZoneColor.Purple => VISUALIZATION_BR_SPHERE_PREFAB_PURPLE, BRZoneColor.Red => VISUALIZATION_BR_SPHERE_PREFAB_RED, _ => throw new ArgumentOutOfRangeException(nameof(BRZoneColor), BRZoneColor, null)
}
;
}
}
public class MapMarkerSettings {
[JsonProperty(LanguageEn ? "Display the block zone on the G map" : "Отображать зону блокировки на G карте")]
public bool IsRaidBlockMarkerEnabled = true;
[JsonProperty(LanguageEn ? "Choose marker type: 0 - Explosion, 1 - Circle, 2 - Explosion + Circle, 3 - Circle + Timer" : "Выберите тип маркера: 0 - Explosion | 1 - Marker Radius | 2 - Explosion + Marker Radius | 3 - Marker Radius + Timer")]
public MarkerTypes RaidBlockMarkerType = MarkerTypes.ExplosionMarkerRadius;
[JsonProperty(LanguageEn ? "Marker color (without #) (For marker types 1, 2, and 3)" : "Цвет маркера (без #) (Для маркера типа 1, 2 и 3)")]
public string MarkerColorHex = "f3ecad";
[JsonProperty(LanguageEn ? "Outline color (without #) (For marker types 1, 2, and 3)" : "Цвет обводки (без #) (Для маркера типа 1, 2 и 3)")]
public string OutlineColorHex = "ff3535";
[JsonProperty(LanguageEn ? "Marker transparency (For marker types 1, 2, and 3)" : "Прозрачность маркера (Для маркера типа 1, 2 и 3)")]
public float MarkerAlpha = 0.5f;
}
}
[JsonProperty(LanguageEn ? "Setting IQChat" : "Настройка IQChat")]
public IQChat IQChatSetting = new IQChat();
public class IQChat {
[JsonProperty(LanguageEn ? "IQChat : Custom prefix in the chat" : "IQChat : Кастомный префикс в чате")]
public String CustomPrefix = "[RaidBlock]";
[JsonProperty(LanguageEn ? "IQChat : Use UI notifications" : "IQChat : Использовать UI уведомления")]
public Boolean UIAlertUse = false;
[JsonProperty(LanguageEn ? "IQChat : Custom avatar in the chat (If required)" : "IQChat : Кастомный аватар в чате(Если требуется)")]
public String CustomAvatar = "0";
}
public class RaidBlockDetect {
[JsonProperty(LanguageEn ? "List of items that will trigger a raid block upon destruction (prefabID)" : "Список предметов за которые при уничтожении будет даваться рейдблок (prefabID)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public HashSet<uint> RbBlackList = new() {
12312312,
}
;
[JsonProperty(LanguageEn ? "List of items that will not trigger a raid block upon destruction (prefabID)" : "Список предметов за которые при уничтожении не будет даваться рейдблок (prefabID)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public HashSet<uint> RbWhiteList = new() {
1231223,
}
;
[JsonProperty(LanguageEn ? "Ignore objects with a maximum health state less than N (0 - disabled)" : "Игнорировать объекты с максимальным состоянием здоровья меньше N (0 - отключено)")]
public int IgnoreEntsHealth = 0;
[JsonProperty(LanguageEn ? "Activate raidblock upon the destruction of own or friends' buildings" : "Активировать рейдблок при уничтожении собственного строения или строения друзей")]
public bool RaidYourself = false;
[JsonProperty(LanguageEn ? "Activate raidblock if there is no tool cupboard in the building" : "Активировать рейдблок если в строении нет шкафа")]
public bool CanRaidIfNotCupboard = false;
[JsonProperty(LanguageEn ? "Setting the activation of the raid block when dealing damage to structures" : "Настройка активации рейд блока при нанесении урона строениям")]
public RaidBlockOnTakeDamage RaidBlockOnTakeDamageHook = new();
public class RaidBlockOnTakeDamage {
[JsonProperty(LanguageEn ? "Activate raid block when dealing damage to structures? (true - yes/false - no)" : "Активировать рейд блок при нанесении урона строениям (true - да/false - нет)")]
public bool ActivateBlockOnTakeDamage = false;
[JsonProperty(LanguageEn ? "Extend raid block upon subsequent damage to structures? (true - yes/false - no)" : "Продлить рейд блок при повторном нанесении урона строениям (true - да/false - нет)")]
public bool UpdateBlockOnTakeDamage = false;
[JsonProperty(LanguageEn ? "Blacklist of items for which raid block will not activate or extend upon damage (ShortName)" : "Черный список предметов за которые при нанесении урона не будет активироваться и продлеваться рейд блок (ShortName)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public HashSet<string> RbOnTakeDamageBlackList = new() {
"torch",
}
;
[JsonProperty(LanguageEn ? "Specify the types of damage caused for which the raid block will be activated and extended when damage is inflicted" : "Укажите типы нанесенного урона за которые при нанесении урона будет активироваться и продлеваться рейд блок", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> RaidDamageTypes = new() {
"Bullet", "Blunt", "Stab", "Slash", "Explosion", "Heat",
}
;
[JsonIgnore]
public List<DamageType> _damageTypes = new();
[JsonProperty(LanguageEn ? "The condition of a structure before blocking will start (percentage)" : "Состояние структуры перед началом блокировки (Процент)")]
public float RbOnTakeDamageMinCondition = 100;
}
}
[JsonProperty(LanguageEn ? "Main raidblock settings" : "Основные настройки рейд-блока")]
public RaidBlock RaidBlockMain = new();
public class RaidBlockUi {
[JsonProperty(LanguageEn ? "Interface variant (0, 1, 2) - example: " : "Вариант интерфейса (0, 1, 2)")]
public int UiType = 0;
[JsonProperty(LanguageEn ? "Interface layer: Overlay - will overlay other UI, Hud - will be overlaid by other interfaces" : "Слой интерфейса : Overlay - будет перекрывать другие UI, Hud - будет перекрываться другим интерфейсом")]
public string Layers = "Hud";
[JsonProperty(LanguageEn ? "Vertical padding" : "Вертикальный отступ")]
public int OffsetY = 0;
[JsonProperty(LanguageEn ? "Horizontal padding" : "Горизонтальный отступ")]
public int OffsetX = 0;
[JsonProperty(LanguageEn ? "Interface settings for variant 0" : "Настройки интерфейса для варианта 0")]
public RaidBlockUiSettings InterfaceSettingsVariant0 = new() {
BackgroundColor = "0.1921569 0.1921569 0.1921569 1", IconColor = "0 0.7764706 1 1", AdditionalElementsColor = "", MainTextColor = "1 1 1 1", SecondaryTextColor = "1 1 1 0.5019608", ProgressBarMainColor = "0.3411765 0.5490196 0.9607843 1", ProgressBarBackgroundColor = "1 1 1 0.1019608", SmoothTransition = 0.222f,
}
;
[JsonProperty(LanguageEn ? "Interface settings for variant 1" : "Настройки интерфейса для варианта 1")]
public RaidBlockUiSettings InterfaceSettingsVariant1 = new() {
BackgroundColor = "0.9607843 0.772549 0.7333333 0.7019608", IconColor = "1 1 1 1", AdditionalElementsColor = "0.9215686 0.3058824 0.172549 1", MainTextColor = "0.1921569 0.1928762 0.1921569 1", SecondaryTextColor = "0.1320755 0.1320755 0.1320755 1", ProgressBarMainColor = "0.9215686 0.3058824 0.172549 1", ProgressBarBackgroundColor = "1 1 1 0.4117647", SmoothTransition = 0.222f
}
;
[JsonProperty(LanguageEn ? "Interface settings for variant 2" : "Настройки интерфейса для варианта 2")]
public RaidBlockUiSettings InterfaceSettingsVariant2 = new() {
BackgroundColor = "0.1921569 0.1921569 0.1921569 1", IconColor = "0.9411765 0.3137255 0.2868762 1", AdditionalElementsColor = "0.9568627 0.3607843 0.2628762 1", MainTextColor = "1 1 1 1", SecondaryTextColor = "1 1 1 0.5019608", ProgressBarMainColor = "1 1 1 1", ProgressBarBackgroundColor = "1 1 1 0.4117647", SmoothTransition = 0.222f
}
;
public class RaidBlockUiSettings {
[JsonProperty(LanguageEn ? "Background color (RGBA)" : "Цвет фона (RGBA)")]
public string BackgroundColor;
[JsonProperty(LanguageEn ? "Icon color (RGBA)" : "Цвет иконки (RGBA)")]
public string IconColor;
[JsonProperty(LanguageEn ? "Color of additional elements (RGBA)" : "Цвет дополнительных элементов (RGBA)")]
public string AdditionalElementsColor;
[JsonProperty(LanguageEn ? "Main text color (RGBA)" : "Цвет основного текста (RGBA)")]
public string MainTextColor;
[JsonProperty(LanguageEn ? "Secondary text Color (RGBA)" : "Цвет второстепенного текста (RGBA)")]
public string SecondaryTextColor;
[JsonProperty(LanguageEn ? "Main color of the progress-bar (RGBA)" : "Основной цвет прогресс-бара (RGBA)")]
public string ProgressBarMainColor;
[JsonProperty(LanguageEn ? "Background Color of the Progress Bar (RGBA)" : "Цвет фона прогресс-бара (RGBA)")]
public string ProgressBarBackgroundColor;
[JsonProperty(LanguageEn ? "Delay before the UI appears and disappears (for smooth transitions)" : "Задержка перед появлением и исчезновением UI (для плавности)")]
public float SmoothTransition;
}
}
}
// С нивеском что-то
/// <summary>
/// - Исправлена выдача рейдблока при убийстве NPC с плагином LootDefender
/// - Добавлен новый пункт в конфигурацию "Запретить телепортироваться домой, если он в радиусе рейдблока" (Работает только с последней с версией 1.8.7 NTeleportation и выше)
/// </summary>
[PluginReference]
Plugin Friends, Clans, IQChat;
private bool IsWhiteList(BaseCombatEntity entity) {
return config.BlockDetect.RbWhiteList.Any(whiteEnt => entity.prefabID == whiteEnt);
}
private void CreateToolGunItem(BasePlayer player, string name, ulong skinId) {
Item toolGun = ItemManager.CreateByName(RB_WHITE_AND_BLACK_LIST_ITEM, 1, skinId);
toolGun.name = name;
toolGun.info.stackable = 1;
player.GiveItem(toolGun);
}
private void ValidateConfig() {
if (config.RaidBlockMain.RaidZoneSphereSettings.DomeTransparencyLevel > 5) {
config.RaidBlockMain.RaidZoneSphereSettings.DomeTransparencyLevel = 3;
}
if (config.BlockDetect.RaidBlockOnTakeDamageHook.ActivateBlockOnTakeDamage) {
if (config.BlockDetect.RaidBlockOnTakeDamageHook.RaidDamageTypes.Count > 0) {
foreach (string damageTypeString in config.BlockDetect.RaidBlockOnTakeDamageHook.RaidDamageTypes) {
if (Enum.TryParse(damageTypeString, out DamageType damageType)) {
config.BlockDetect.RaidBlockOnTakeDamageHook._damageTypes.Add(damageType);
}
else {
PrintError($"[Configuration] Invalid damage type: {damageTypeString}.Removing from list.Available types: {string.Join(", ", Enum.GetNames(typeof(DamageType)))}");
}
}
config.BlockDetect.RaidBlockOnTakeDamageHook.RaidDamageTypes.RemoveAll(damageTypeString => !Enum.TryParse(damageTypeString, out DamageType _));
}
}
}
private const Boolean LanguageEn = false;
private object OnStructureUpgrade(BuildingBlock block, BasePlayer player, BuildingGrade.Enum grade) => CanActions(player);
private void DrawUI_RB_Updated(BasePlayer player, float timeLeft, bool upd = false) {
string Interface = InterfaceBuilder.GetInterface(InterfaceBuilder.RB_PROGRESS_BAR);
if (Interface == null) return;
double factor = InterfaceBuilder.Factor * timeLeft / config.RaidBlockMain.RaidBlockDuration;
Interface = Interface.Replace("%left%", factor.ToString(CultureInfo.InvariantCulture));
Interface = Interface.Replace("%TimeLeft%", "RAIDBLOCK_UI_TIMER".GetAdaptedMessage(player.UserIDString, timeLeft.ToTimeFormat()));
if(!upd) Interface = Interface.Replace("0.222", "0");
CuiHelper.DestroyUi(player, InterfaceBuilder.RB_PROGRESS);
CuiHelper.DestroyUi(player, InterfaceBuilder.RB_PROGRESS_TIMER);
CuiHelper.AddUi(player, Interface);
}
private List<RaidableZone> _raidZoneComponents = new();
private enum MarkerTypes {
Explosion, MarkerRadius, ExplosionMarkerRadius, MarkerRadiusTimer,
}
[ChatCommand("rb.black")]
private void RaidBlockDetectBlackList(BasePlayer player) {
if (!HasPermission(player)) return;
string itemName = "RAIDBLOCK_TOOLGUN_BLACKLIST_ITEM_NAME".GetAdaptedMessage(player.UserIDString);
if (FindItemInInventory(player, RB_BLACKLIST_ITEM_SKIN)) {
GameTipsSendPlayer(player, "RAIDBLOCK_TOOLGUN_ALREADY_IN_INVENTORY".GetAdaptedMessage(player.UserIDString, itemName), error : true);
return;
}
CreateToolGunItem(player, itemName, RB_BLACKLIST_ITEM_SKIN);
GameTipsSendPlayer(player, "RAIDBLOCK_TOOLGUN_BLACKLIST_USAGE".GetAdaptedMessage(player.UserIDString, itemName));
}
private bool IsFriends(BasePlayer player, ulong targetID) {
List<ulong> friendList = GetFriendList(player);
bool
// ... [Code preview truncated due to length. Full source in attached file] ...