using System; using System.Linq; using System.Collections.Generic; using System.Text.RegularExpressions; using Oxide.Core; using Oxide.Core.Plugins; using Oxide.Game.Rust.Cui; using Newtonsoft.Json.Linq; using UnityEngine; using Facepunch; using Rust; namespace Oxide.Plugins { [Info ("No Escape", "Calytic", "2.1.35")] [Description ("Prevent commands/actions while raid and/or combat is occuring")] class NoEscape : RustPlugin { #region Setup & Configuration List blockTypes = new List () { "remove", "tp", "bank", "trade", "recycle", "shop", "bgrade", "build", "repair", "upgrade", "vend", "kit", "assignbed", "craft", "mailbox", "backpack" }; // COMBAT SETTINGS bool combatBlock; static float combatDuration; bool combatOnHitPlayer; float combatOnHitPlayerMinCondition; float combatOnHitPlayerMinDamage; bool combatOnTakeDamage; float combatOnTakeDamageMinCondition; float combatOnTakeDamageMinDamage; bool combatOnHitNPC; bool combatOnTakeDamageNPC; // RAID BLOCK SETTINGS bool raidBlock; static float raidDuration; float raidDistance; bool blockOnDamage; float blockOnDamageMinCondition; bool blockOnDestroy; // RAID-ONLY SETTINGS bool ownerCheck; bool blockUnowned; bool blockAll; // IGNORES ALL OTHER CHECKS bool ownerBlock; bool cupboardShare; bool friendShare; bool clanShare; bool clanCheck; bool friendCheck; bool raiderBlock; List raidDamageTypes; List raidDeathTypes; List combatDamageTypes; // RAID UNBLOCK SETTINGS bool raidUnblockOnDeath; bool raidUnblockOnWakeup; bool raidUnblockOnRespawn; // COMBAT UNBLOCK SETTINGS bool combatUnblockOnDeath; bool combatUnblockOnWakeup; bool combatUnblockOnRespawn; float cacheTimer; // MESSAGES bool raidBlockNotify; bool combatBlockNotify; bool useZoneManager; bool zoneEnter; bool zoneLeave; bool useRaidableBases; bool raidableZoneEnter; bool raidableZoneLeave; bool sendUINotification; bool sendChatNotification; bool sendGUIAnnouncementsNotification; bool sendLustyMapNotification; string GUIAnnouncementTintColor = "Red"; string GUIAnnouncementTextColor = "White"; string LustyMapIcon = "special"; float LustyMapDuration = 150f; Dictionary zones = new Dictionary (); Dictionary> memberCache = new Dictionary> (); Dictionary clanCache = new Dictionary (); Dictionary> friendCache = new Dictionary> (); Dictionary lastClanCheck = new Dictionary (); Dictionary lastCheck = new Dictionary (); Dictionary lastFriendCheck = new Dictionary (); Dictionary prefabBlockCache = new Dictionary (); internal Dictionary blockBehaviors = new Dictionary (); public static NoEscape plugin; [PluginReference] Plugin Clans, Friends, ZoneManager, GUIAnnouncements, LustyMap; readonly int cupboardMask = LayerMask.GetMask ("Deployed"); readonly int blockLayer = LayerMask.GetMask ("Player (Server)"); Dictionary _cachedExcludedWeapons = new Dictionary (); List blockedPrefabs = new List () { "door", "window.bars", "floor.ladder.hatch", "floor.frame", "wall.frame", "shutter", "external" }; List exceptionPrefabs = new List () { "ladder.wooden" }; List exceptionWeapons = new List () { "torch" }; private List GetDefaultRaidDamageTypes () { return new List () { DamageType.Bullet, DamageType.Blunt, DamageType.Stab, DamageType.Slash, DamageType.Explosion, DamageType.Heat }.Select (x => x.ToString ()).ToList (); } private List GetDefaultCombatDamageTypes () { return new List () { DamageType.Bullet, DamageType.Arrow, DamageType.Blunt, DamageType.Stab, DamageType.Slash, DamageType.Explosion, DamageType.Heat, DamageType.ElectricShock }.Select (x => x.ToString ()).ToList (); } Dictionary blockWhenRaidDamageDefault = new Dictionary () { {"enabled", true}, {"minCondition", 100f}, }; Dictionary blockWhenCombatDamageDefault = new Dictionary () { {"enabled", false}, {"minCondition", 100f}, {"minDamage", 1f}, }; static Regex _htmlRegex = new Regex ("<.*?>", RegexOptions.Compiled); protected override void LoadDefaultConfig () { Config ["VERSION"] = Version.ToString (); // RAID SETTINGS Config ["Raid", "Block", "enabled"] = true; Config ["Raid", "Block", "duration"] = 300f; // 5 minutes Config ["Raid", "Block", "distance"] = 100f; Config ["Raid", "Block", "notify"] = true; Config ["Raid", "Block", "damageTypes"] = GetDefaultRaidDamageTypes (); Config ["Raid", "Block", "deathTypes"] = GetDefaultRaidDamageTypes(); Config ["Raid", "Block", "includePrefabs"] = blockedPrefabs; Config ["Raid", "Block", "excludePrefabs"] = exceptionPrefabs; Config ["Raid", "Block", "excludeWeapons"] = exceptionWeapons; Config ["Raid", "BlockWhen", "damage"] = blockWhenRaidDamageDefault; Config ["Raid", "BlockWhen", "destroy"] = true; Config ["Raid", "BlockWhen", "unowned"] = false; Config ["Raid", "BlockWho", "everyone"] = true; Config ["Raid", "BlockWho", "owner"] = false; Config ["Raid", "BlockWho", "cupboardAuthorized"] = false; Config ["Raid", "BlockWho", "clan"] = false; Config ["Raid", "BlockWho", "friends"] = false; Config ["Raid", "BlockWho", "raider"] = false; Config ["Raid", "BlockExcept", "owner"] = true; Config ["Raid", "BlockExcept", "friends"] = false; Config ["Raid", "BlockExcept", "clan"] = false; Config ["Raid", "Zone", "enabled"] = false; Config ["Raid", "Zone", "enter"] = true; Config ["Raid", "Zone", "leave"] = false; Config ["Raid", "Map", "enabled"] = false; Config ["Raid", "Map", "icon"] = "special"; Config ["Raid", "Map", "duration"] = 150f; Config ["Raid", "UnblockWhen", "death"] = true; Config ["Raid", "UnblockWhen", "wakeup"] = false; Config ["Raid", "UnblockWhen", "respawn"] = true; // COMBAT SETTINGS Config ["Combat", "Block", "enabled"] = false; Config ["Combat", "Block", "duration"] = 180f; // 3 minutes Config ["Combat", "Block", "notify"] = true; Config ["Combat", "Block", "damageTypes"] = GetDefaultCombatDamageTypes (); Config ["Combat", "BlockWhen", "giveDamage"] = blockWhenCombatDamageDefault; Config ["Combat", "BlockWhen", "takeDamage"] = blockWhenCombatDamageDefault; Config ["Combat", "BlockWhen", "npcGiveDamage"] = false; Config ["Combat", "BlockWhen", "npcTakeDamage"] = false; Config ["Combat", "UnblockWhen", "death"] = true; Config ["Combat", "UnblockWhen", "wakeup"] = false; Config ["Combat", "UnblockWhen", "respawn"] = true; Config ["Settings", "cacheMinutes"] = 1f; Config ["Settings", "Block", "Types"] = blockTypes; Config ["Notifications", "UI"] = true; Config ["Notifications", "Chat"] = true; Config ["Notifications", "GUIAnnouncements", "enabled"] = false; Config ["Notifications", "GUIAnnouncements", "backgroundColor"] = "Red"; Config ["Notifications", "GUIAnnouncements", "textColor"] = "White"; Config ["VERSION"] = Version.ToString (); } void Loaded () { LoadMessages (); } void Unload () { if (useZoneManager) foreach (var zone in zones.ToList ()) EraseZone (zone.Value.zoneid); var objects = GameObject.FindObjectsOfType (typeof (RaidBlock)); if (objects != null) foreach (var gameObj in objects) if (!((RaidBlock)gameObj).Active) GameObject.Destroy (gameObj); objects = GameObject.FindObjectsOfType (typeof (CombatBlock)); if (objects != null) foreach (var gameObj in objects) if (!((CombatBlock)gameObj).Active) GameObject.Destroy (gameObj); } void LoadMessages () { lang.RegisterMessages (new Dictionary { { "Raid Blocked Message", "You may not do that while raid blocked ({time})" }, { "Combat Blocked Message", "You may do that while a in combat ({time})" }, { "Raid Block Complete", "You are no longer raid blocked." }, { "Combat Block Complete", "You are no longer combat blocked." }, { "Raid Block Notifier", "You are raid blocked for {time}" }, { "Combat Block Notifier", "You are combat blocked for {time}" }, { "Combat Block UI Message", "COMBAT BLOCK" }, { "Raid Block UI Message", "RAID BLOCK" }, { "Unit Seconds", "second(s)" }, { "Unit Minutes", "minute(s)" }, { "Prefix", string.Empty } }, this); } void CheckConfig () { if (Config ["VERSION"] == null) { // FOR COMPATIBILITY WITH INITIAL VERSIONS WITHOUT VERSIONED CONFIG ReloadConfig (); } else if (GetConfig ("VERSION", string.Empty) != Version.ToString ()) { // ADDS NEW, IF ANY, CONFIGURATION OPTIONS ReloadConfig (); } } protected void ReloadConfig () { Config ["VERSION"] = Version.ToString (); // NEW CONFIGURATION OPTIONS HERE // END NEW CONFIGURATION OPTIONS PrintToConsole ("Upgrading configuration file"); SaveConfig (); } void OnServerInitialized () { NoEscape.plugin = this; permission.RegisterPermission ("noescape.disable", this); blockTypes = GetConfig ("Settings", "Block", "Types", blockTypes); foreach (string command in blockTypes) { permission.RegisterPermission ("noescape.raid." + command + "block", this); permission.RegisterPermission ("noescape.combat." + command + "block", this); } CheckConfig (); // RAID SETTINGS raidBlock = GetConfig ("Raid", "Block", "enabled", true); raidDuration = GetConfig ("Raid", "Block", "duration", 300f); raidDistance = GetConfig ("Raid", "Block", "distance", 100f); raidBlockNotify = GetConfig ("Raid", "Block", "notify", true); raidDamageTypes = GetConfig ("Raid", "Block", "damageTypes", GetDefaultRaidDamageTypes ()); raidDeathTypes = GetConfig("Raid", "Block", "deathTypes", GetDefaultRaidDamageTypes()); blockedPrefabs = GetConfig ("Raid", "Block", "includePrefabs", blockedPrefabs); exceptionPrefabs = GetConfig ("Raid", "Block", "excludePrefabs", exceptionPrefabs); exceptionWeapons = GetConfig ("Raid", "Block", "excludeWeapons", exceptionWeapons); Dictionary blockOnRaidDamageDetails = GetConfig ("Raid", "BlockWhen", "damage", blockWhenRaidDamageDefault); if (blockOnRaidDamageDetails.ContainsKey ("enabled")) { blockOnDamage = (bool)blockOnRaidDamageDetails ["enabled"]; } else { blockOnDamage = true; } if (blockOnRaidDamageDetails.ContainsKey ("minCondition")) { blockOnDamageMinCondition = Convert.ToSingle (blockOnRaidDamageDetails ["minCondition"]); } else { blockOnDamageMinCondition = 100f; } blockOnDestroy = GetConfig ("Raid", "BlockWhen", "destroy", true); blockUnowned = GetConfig ("Raid", "BlockWhen", "unowned", false); blockAll = GetConfig ("Raid", "BlockWho", "everyone", true); ownerBlock = GetConfig ("Raid", "BlockWho", "owner", false); friendShare = GetConfig ("Raid", "BlockWho", "friends", false); clanShare = GetConfig ("Raid", "BlockWho", "clan", false); cupboardShare = GetConfig ("Raid", "BlockWho", "cupboardAuthorized", false); raiderBlock = GetConfig ("Raid", "BlockWho", "raider", false); ownerCheck = GetConfig ("Raid", "BlockExcept", "owner", true); friendCheck = GetConfig ("Raid", "BlockExcept", "friends", false); clanCheck = GetConfig ("Raid", "BlockExcept", "clan", false); useZoneManager = GetConfig ("Raid", "Zone", "enabled", false); zoneEnter = GetConfig ("Raid", "Zone", "enter", true); zoneLeave = GetConfig ("Raid", "Zone", "leave", false); useRaidableBases = GetConfig ("Raid", "RaidableBases", "enabled", false); raidableZoneEnter = GetConfig ("Raid", "RaidableBases", "enter", true); raidableZoneLeave = GetConfig ("Raid", "RaidableBases", "leave", false); sendLustyMapNotification = GetConfig ("Raid", "Map", "enabled", false); LustyMapIcon = GetConfig ("Raid", "Map", "icon", "special"); LustyMapDuration = GetConfig ("Raid", "Map", "duration", 150f); raidUnblockOnDeath = GetConfig ("Raid", "UnblockWhen", "death", true); raidUnblockOnWakeup = GetConfig ("Raid", "UnblockWhen", "wakeup", false); raidUnblockOnRespawn = GetConfig ("Raid", "UnblockWhen", "respawn", true); // COMBAT SETTINGS combatBlock = GetConfig ("Combat", "Block", "enabled", false); combatDuration = GetConfig ("Combat", "Block", "duration", 180f); combatBlockNotify = GetConfig ("Combat", "Block", "notify", true); combatDamageTypes = GetConfig ("Combat", "Block", "damageTypes", GetDefaultCombatDamageTypes ()); //combatOnHitPlayer = GetConfig ("Combat", "BlockWhen", "giveDamage", true); Dictionary blockOnCombatGiveDamageDetails = GetConfig ("Combat", "BlockWhen", "giveDamage", blockWhenCombatDamageDefault); if (blockOnCombatGiveDamageDetails.ContainsKey ("enabled")) { combatOnHitPlayer = (bool)blockOnCombatGiveDamageDetails ["enabled"]; } else { combatOnHitPlayer = false; } if (blockOnCombatGiveDamageDetails.ContainsKey ("minCondition")) { combatOnHitPlayerMinCondition = Convert.ToSingle (blockOnCombatGiveDamageDetails ["minCondition"]); } else { combatOnHitPlayerMinCondition = 100f; } //combatOnTakeDamage = GetConfig ("Combat", "BlockWhen", "takeDamage", true); Dictionary blockOnCombatTakeDamageDetails = GetConfig ("Combat", "BlockWhen", "takeDamage", blockWhenCombatDamageDefault); if (blockOnCombatTakeDamageDetails.ContainsKey ("enabled")) { combatOnTakeDamage = (bool)blockOnCombatTakeDamageDetails ["enabled"]; } else { combatOnTakeDamage = false; } if (blockOnCombatTakeDamageDetails.ContainsKey ("minCondition")) { combatOnTakeDamageMinCondition = Convert.ToSingle (blockOnCombatTakeDamageDetails ["minCondition"]); } else { combatOnTakeDamageMinCondition = 100f; } if (blockOnCombatTakeDamageDetails.ContainsKey ("minDamage")) { combatOnTakeDamageMinDamage = Convert.ToSingle (blockOnCombatTakeDamageDetails ["minDamage"]); } else { combatOnTakeDamageMinDamage = 1f; } combatOnHitNPC = GetConfig ("Combat", "BlockWhen", "npcGiveDamage", false); combatOnTakeDamageNPC = GetConfig ("Combat", "BlockWhen", "npcTakeDamage", false); combatUnblockOnDeath = GetConfig ("Combat", "UnblockWhen", "death", true); combatUnblockOnWakeup = GetConfig ("Combat", "UnblockWhen", "wakeup", false); combatUnblockOnRespawn = GetConfig ("Combat", "UnblockWhen", "respawn", true); cacheTimer = GetConfig ("Settings", "cacheMinutes", 1f); sendUINotification = GetConfig ("Notifications", "UI", true); sendChatNotification = GetConfig ("Notifications", "Chat", true); sendGUIAnnouncementsNotification = GetConfig ("Notifications", "GUIAnnouncements", "enabled", false); GUIAnnouncementTintColor = GetConfig ("Notifications", "GUIAnnouncements", "backgroundColor", "Red"); GUIAnnouncementTextColor = GetConfig ("Notifications", "GUIAnnouncements", "textColor", "White"); if ((clanShare || clanCheck) && !Clans) { clanShare = false; clanCheck = false; PrintWarning ("Clans not found! All clan options disabled. Cannot use clan options without this plugin. http://oxidemod.org/plugins/clans.2087"); } if (friendShare && !Friends) { friendShare = false; friendCheck = false; PrintWarning ("Friends not found! All friend options disabled. Cannot use friend options without this plugin. http://oxidemod.org/plugins/friends-api.686"); } if (useZoneManager && !ZoneManager) { useZoneManager = false; PrintWarning ("ZoneManager not found! All zone options disabled. Cannot use zone options without this plugin. http://oxidemod.org/plugins/zones-manager.739"); } if (sendGUIAnnouncementsNotification && !GUIAnnouncements) { sendGUIAnnouncementsNotification = false; PrintWarning ("GUIAnnouncements not found! GUI announcement option disabled. Cannot use gui announcement integration without this plugin. http://oxidemod.org/plugins/gui-announcements.1222"); } if (sendLustyMapNotification && !LustyMap) { sendLustyMapNotification = false; PrintWarning ("LustyMap not found! LustyMap notification option disabled. Cannot use LustyMap integration without this plugin. http://oxidemod.org/plugins/lustymap.1333"); } if (sendLustyMapNotification && LustyMap && LustyMapDuration <= 0) { PrintWarning ("LustyMap icon duration is zero, no icon will be displayed"); } UnsubscribeHooks (); } void UnsubscribeHooks () { if (!blockOnDestroy && !raidUnblockOnDeath && !combatUnblockOnDeath) Unsubscribe ("OnEntityDeath"); if (!raidUnblockOnWakeup && !combatUnblockOnWakeup) Unsubscribe ("OnPlayerSleepEnded"); if (!combatOnTakeDamage && !combatOnHitPlayer) Unsubscribe ("OnPlayerAttack"); if (!blockOnDamage) Unsubscribe ("OnEntityTakeDamage"); if (!blockTypes.Contains ("repair")) Unsubscribe ("OnStructureRepair"); if (!blockTypes.Contains ("upgrade")) Unsubscribe ("OnStructureUpgrade"); if (!blockTypes.Contains ("mailbox")) Unsubscribe ("CanUseMailbox"); if (!blockTypes.Contains ("vend")) Unsubscribe ("CanUseVending"); if (!blockTypes.Contains ("build")) Unsubscribe ("CanBuild"); if (!blockTypes.Contains ("assignbed")) Unsubscribe ("CanAssignBed"); if (!blockTypes.Contains ("craft")) Unsubscribe ("CanCraft"); if (!blockTypes.Contains ("backpack")) Unsubscribe ("CanOpenBackpack"); if(!useZoneManager) { Unsubscribe ("OnEnterZone"); Unsubscribe ("OnExitZone"); } if(!useRaidableBases) { Unsubscribe ("OnPlayerEnteredRaidableBase"); Unsubscribe ("OnPlayerExitedRaidableBase"); } } #endregion #region Classes public class RaidZone { public string zoneid; public Vector3 position; public Timer timer; public RaidZone (string zoneid, Vector3 position) { this.zoneid = zoneid; this.position = position; } public float Distance (RaidZone zone) { return Vector3.Distance (position, zone.position); } public float Distance (Vector3 pos) { return Vector3.Distance (position, pos); } public RaidZone ResetTimer () { if (timer is Timer && !timer.Destroyed) timer.Destroy (); return this; } } public abstract class BlockBehavior : MonoBehaviour { protected BasePlayer player; public DateTime lastBlock = DateTime.MinValue; public DateTime lastNotification = DateTime.MinValue; internal DateTime lastUINotification = DateTime.MinValue; internal Timer timer; internal Action notifyCallback; internal string iconUID; internal bool moved; public void CopyFrom (BlockBehavior behavior) { lastBlock = behavior.lastBlock; lastNotification = behavior.lastNotification; lastUINotification = behavior.lastUINotification; timer = behavior.timer; notifyCallback = behavior.notifyCallback; iconUID = behavior.iconUID; NotificationWindow = behavior.NotificationWindow; } internal abstract float Duration { get; } internal abstract CuiRectTransformComponent NotificationWindow { get; set; } internal abstract string notifyMessage { get; } internal string BlockName { get { return GetType ().Name; } } public bool Active { get { if (lastBlock > DateTime.MinValue) { TimeSpan ts = DateTime.Now - lastBlock; if (ts.TotalSeconds < Duration) { return true; } } GameObject.Destroy (this); return false; } } void Awake () { player = GetComponent (); if (plugin.blockBehaviors.ContainsKey (player.userID)) { plugin.blockBehaviors.Remove (player.userID); } plugin.blockBehaviors.Add (player.userID, this); } void Destroy () { if (!moved) { Stop (); } CancelInvoke ("Update"); } void Update () { if (!plugin.sendUINotification) return; bool send = false; if (lastUINotification == DateTime.MinValue) { lastUINotification = DateTime.Now; send = true; } else { TimeSpan ts = DateTime.Now - lastUINotification; if (ts.TotalSeconds > 2) { send = true; } else { send = false; } } if (player is BasePlayer && player.IsConnected) { if (!Active) { CuiHelper.DestroyUi (player, "BlockMsg" + BlockName); } if (send && Active) { lastUINotification = DateTime.Now; SendGUI (); } } } public void Stop () { if (notifyCallback is Action) notifyCallback.Invoke (); if (timer is Timer && !timer.Destroyed) timer.Destroy (); if (plugin.sendUINotification && player is BasePlayer && player.IsConnected) CuiHelper.DestroyUi (player, "BlockMsg" + BlockName); plugin.blockBehaviors.Remove (player.userID); GameObject.Destroy (this); } public void Notify (Action callback) { if (plugin.sendUINotification) SendGUI (); notifyCallback = callback; if (timer is Timer && !timer.Destroyed) timer.Destroy (); timer = plugin.timer.In (Duration, callback); } private string FormatTime (TimeSpan ts) { if (ts.Days > 0) return string.Format ("{0}D, {1}H", ts.Days, ts.Hours); if (ts.Hours > 0) return string.Format ("{0}H {1}M", ts.Hours, ts.Minutes); return string.Format ("{0}M {1}S", ts.Minutes, ts.Seconds); } void SendGUI () { TimeSpan ts = lastBlock.AddSeconds (Duration) - DateTime.Now; string countDown = FormatTime (ts); CuiHelper.DestroyUi (player, "BlockMsg" + BlockName); var elements = new CuiElementContainer (); var BlockMsg = elements.Add (new CuiPanel { Image = { Color = "0.95 0 0.02 0.67" }, RectTransform = { AnchorMax = NotificationWindow.AnchorMax, AnchorMin = NotificationWindow.AnchorMin } }, "Hud", "BlockMsg" + BlockName); elements.Add (new CuiElement { Parent = BlockMsg, Components = { new CuiRawImageComponent { Sprite = "assets/icons/explosion.png", Color = "0.95 0 0.02 0.67" }, new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "0.13 1" } } }); elements.Add (new CuiLabel { RectTransform = { AnchorMin = "0.15 0", AnchorMax = "0.82 1" }, Text = { Text = notifyMessage, FontSize = 11, Align = TextAnchor.MiddleLeft, } }, BlockMsg); elements.Add (new CuiElement { Name = "TimerPanel", Parent = BlockMsg, Components = { new CuiImageComponent { Color = "0 0 0 0.64", ImageType = UnityEngine.UI.Image.Type.Filled }, new CuiRectTransformComponent { AnchorMin = "0.73 0", AnchorMax = "1 1" } } }); elements.Add (new CuiLabel { RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" }, Text = { Text = countDown, FontSize = 12, Align = TextAnchor.MiddleCenter, } }, "TimerPanel"); CuiHelper.AddUi (player, elements); } } public class CombatBlock : BlockBehavior { internal override float Duration { get { return combatDuration; } } internal override string notifyMessage { get { return GetMsg ("Combat Block UI Message", player); } } CuiRectTransformComponent _notificationWindow = null; internal override CuiRectTransformComponent NotificationWindow { get { if (_notificationWindow != null) { return _notificationWindow; } return _notificationWindow = new CuiRectTransformComponent () { AnchorMin = "0.44 0.15", AnchorMax = "0.56 0.18" }; } set { _notificationWindow = value; } } } public class RaidBlock : BlockBehavior { internal override float Duration { get { return raidDuration; } } internal override string notifyMessage { get { return GetMsg ("Raid Block UI Message", player); } } private CuiRectTransformComponent _notificationWindow = null; internal override CuiRectTransformComponent NotificationWindow { get { if (_notificationWindow != null) { return _notificationWindow; } return _notificationWindow = new CuiRectTransformComponent () { AnchorMin = "0.87 0.39", AnchorMax = "0.99 0.42" }; } set { _notificationWindow = value; } } } #endregion #region Oxide Hooks void OnEntityTakeDamage (BaseCombatEntity entity, HitInfo hitInfo) { if (!blockOnDamage || !raidBlock) return; if (hitInfo == null || hitInfo.Initiator == null || !IsEntityBlocked (entity) || hitInfo.Initiator.transform == null) return; if (!IsRaidDamage (hitInfo.damageTypes)) return; if (IsExcludedWeapon (hitInfo?.WeaponPrefab?.ShortPrefabName)) return; if (GetHealthPercent (entity, hitInfo.damageTypes.Total ()) > blockOnDamageMinCondition) { return; } StructureAttack (entity, hitInfo.Initiator, hitInfo?.WeaponPrefab?.ShortPrefabName, hitInfo.HitPositionWorld); } void OnPlayerConnected (BasePlayer player) { BlockBehavior behavior; if (blockBehaviors.TryGetValue (player.userID, out behavior)) { if (behavior is RaidBlock) { var raidBlockComponent = player.gameObject.AddComponent (); raidBlockComponent.CopyFrom (behavior); } else if (behavior is CombatBlock) { var combatBlockComponent = player.gameObject.AddComponent (); combatBlockComponent.CopyFrom (behavior); } behavior.moved = true; GameObject.Destroy (behavior); } } void OnPlayerAttack (BasePlayer attacker, HitInfo hitInfo) { if (!combatBlock || !(hitInfo.HitEntity is BasePlayer)) return; if (!combatOnHitNPC && hitInfo.HitEntity.IsNpc) return; if (!combatOnTakeDamageNPC && attacker.IsNpc) { return; } if (!IsCombatDamage (hitInfo.damageTypes)) return; float totalDamage = hitInfo.damageTypes.Total (); BasePlayer target = hitInfo.HitEntity as BasePlayer; if (combatOnTakeDamage) { if (GetHealthPercent (target, hitInfo.damageTypes.Total ()) > combatOnTakeDamageMinCondition) { return; } if (totalDamage < combatOnTakeDamageMinDamage) { return; } StartCombatBlocking (target); } if (combatOnHitPlayer) { if (GetHealthPercent (attacker, hitInfo.damageTypes.Total ()) > combatOnHitPlayerMinCondition) { return; } if (totalDamage < combatOnHitPlayerMinDamage) { return; } StartCombatBlocking (attacker); } } void OnEntityDeath (BaseCombatEntity entity, HitInfo hitInfo) { if (blockOnDestroy && raidBlock) { if (hitInfo == null || hitInfo.Initiator == null || !IsDeathDamage (hitInfo.damageTypes) || !IsEntityBlocked (entity)) return; StructureAttack (entity, hitInfo.Initiator, hitInfo?.WeaponPrefab?.ShortPrefabName, hitInfo.HitPositionWorld); } if (entity.ToPlayer () == null) return; var player = entity.ToPlayer (); RaidBlock raidBlocker; if (raidBlock && raidUnblockOnDeath && TryGetBlocker (player, out raidBlocker)) { timer.In (0.3f, delegate () { raidBlocker.Stop (); }); } CombatBlock combatBlocker; if (combatBlock && combatUnblockOnDeath && TryGetBlocker (player, out combatBlocker)) { timer.In (0.3f, delegate () { combatBlocker.Stop (); }); } } void OnPlayerSleepEnded (BasePlayer player) { if (player == null) return; RaidBlock raidBlocker; if (raidBlock && raidUnblockOnWakeup && TryGetBlocker (player, out raidBlocker)) { timer.In (0.3f, delegate () { raidBlocker.Stop (); }); } CombatBlock combatBlocker; if (combatBlock && combatUnblockOnWakeup && TryGetBlocker (player, out combatBlocker)) { timer.In (0.3f, delegate () { combatBlocker.Stop (); }); } } void OnPlayerRespawned (BasePlayer player) { if (player == null) return; RaidBlock raidBlocker; if (raidBlock && raidUnblockOnRespawn && TryGetBlocker (player, out raidBlocker)) { timer.In (0.3f, delegate () { raidBlocker.Stop (); }); } CombatBlock combatBlocker; if (combatBlock && combatUnblockOnRespawn && TryGetBlocker (player, out combatBlocker)) { timer.In (0.3f, delegate () { combatBlocker.Stop (); }); } } object CanLootEntity(BasePlayer player, StorageContainer container) { if(container?.GetEntity() is Recycler) { object reply = CanDo("recycle", player); if (reply != null && IsBlocked(player)) { player.ChatMessage((string)reply); return true; } } return null; } #endregion #region Block Handling void StructureAttack (BaseEntity targetEntity, BaseEntity sourceEntity, string weapon, Vector3 hitPosition) { BasePlayer source = null; if (sourceEntity.ToPlayer () is BasePlayer) source = sourceEntity.ToPlayer (); else { ulong ownerID = sourceEntity.OwnerID; if (ownerID.IsSteamId ()) source = BasePlayer.FindByID (ownerID); else return; } if (source == null) return; List sourceMembers = null; if (targetEntity.OwnerID.IsSteamId () || (blockUnowned && !targetEntity.OwnerID.IsSteamId ())) { if (clanCheck || friendCheck) sourceMembers = getFriends (source.UserIDString); if (blockAll) { BlockAll (source, targetEntity, sourceMembers); } else { if (ownerBlock) OwnerBlock (source, sourceEntity, targetEntity.OwnerID, targetEntity.transform.position, sourceMembers); if (raiderBlock) RaiderBlock (source, targetEntity.OwnerID, targetEntity.transform.position, sourceMembers); } } } float GetHealthPercent (BaseEntity entity, float damage = 0f) { return (entity.Health () - damage) * 100f / entity.MaxHealth (); } void BlockAll (BasePlayer source, BaseEntity targetEntity, List sourceMembers = null) { if (ShouldBlockEscape (targetEntity.OwnerID, source.userID, sourceMembers)) { StartRaidBlocking (source, targetEntity.transform.position); } var checkSourceMembers = false; if (targetEntity.OwnerID == source.userID || (sourceMembers is List && sourceMembers.Contains (targetEntity.OwnerID.ToString ()))) { checkSourceMembers = true; } var nearbyTargets = Pool.GetList (); Vis.Entities (targetEntity.transform.position, raidDistance, nearbyTargets, blockLayer); if (nearbyTargets.Count > 0) { RaidBlock blocker; foreach (BasePlayer nearbyTarget in nearbyTargets) { if (nearbyTarget.IsNpc) continue; if (nearbyTarget.userID == source.userID) continue; if (TryGetBlocker (nearbyTarget, out blocker) && blocker.Active) { StartRaidBlocking (nearbyTarget, targetEntity.transform.position); } else if (ShouldBlockEscape (nearbyTarget.userID, source.userID, checkSourceMembers ? sourceMembers : null)) { StartRaidBlocking (nearbyTarget, targetEntity.transform.position); } } } Pool.FreeList (ref nearbyTargets); } void OwnerBlock (BasePlayer source, BaseEntity sourceEntity, ulong target, Vector3 position, List sourceMembers = null) { if (!ShouldBlockEscape (target, source.userID, sourceMembers)) return; var targetMembers = new List (); if (clanShare || friendShare) targetMembers = getFriends (target.ToString ()); var nearbyTargets = Pool.GetList (); Vis.Entities (position, raidDistance, nearbyTargets, blockLayer); if (cupboardShare) sourceMembers = CupboardShare (target.ToString (), position, sourceEntity, sourceMembers); if (nearbyTargets.Count > 0) { foreach (BasePlayer nearbyTarget in nearbyTargets) { if (nearbyTarget.IsNpc) continue; if (nearbyTarget.userID == target || (targetMembers != null && targetMembers.Contains (nearbyTarget.UserIDString))) StartRaidBlocking (nearbyTarget, position); } } Pool.FreeList (ref nearbyTargets); } List CupboardShare (string owner, Vector3 position, BaseEntity sourceEntity, List sourceMembers = null) { var nearbyCupboards = Pool.GetList (); Vis.Entities (position, raidDistance, nearbyCupboards, cupboardMask); if (sourceMembers == null) sourceMembers = new List (); List cupboardMembers = new List (); var sourcePlayer = sourceEntity as BasePlayer; if (sourcePlayer != null) { foreach (var cup in nearbyCupboards) { if (cup.IsAuthed (sourcePlayer)) { bool ownerOrFriend = false; if (owner == cup.OwnerID.ToString ()) ownerOrFriend = true; foreach (var member in sourceMembers) { if (member == cup.OwnerID.ToString ()) ownerOrFriend = true; } if (ownerOrFriend) foreach (var proto in cup.authorizedPlayers) if (!sourceMembers.Contains (proto.userid.ToString ())) cupboardMembers.Add (proto.userid.ToString ()); } } } sourceMembers.AddRange (cupboardMembers); Pool.FreeList (ref nearbyCupboards); return sourceMembers; } void RaiderBlock (BasePlayer source, ulong target, Vector3 position, List sourceMembers = null) { if (!ShouldBlockEscape (target, source.userID, sourceMembers)) return; var targetMembers = new List (); if ((clanShare || friendShare) && sourceMembers == null) sourceMembers = getFriends (source.UserIDString); var nearbyTargets = Pool.GetList (); Vis.Entities (position, raidDistance, nearbyTargets, blockLayer); if (nearbyTargets.Count > 0) { foreach (BasePlayer nearbyTarget in nearbyTargets) { if (nearbyTarget.IsNpc) continue; if (nearbyTarget == source || (sourceMembers != null && sourceMembers.Contains (nearbyTarget.UserIDString))) StartRaidBlocking (nearbyTarget, position); } } Pool.FreeList (ref nearbyTargets); } #endregion #region API bool IsBlocked (string target) { var player = BasePlayer.Find (target); if (player is BasePlayer) { return IsBlocked (player); } return false; } bool IsBlocked (BasePlayer target) { if (IsBlocked (target) || IsBlocked (target)) return true; return false; } public bool IsBlocked (BasePlayer target) where T : BlockBehavior { T behavior; if (TryGetBlocker (target, out behavior) && behavior.Active) return true; return false; } bool IsRaidBlocked (BasePlayer target) { return IsBlocked (target); } bool IsCombatBlocked (BasePlayer target) { return IsBlocked (target); } bool IsEscapeBlocked (string target) { var player = BasePlayer.Find (target); if (player is BasePlayer) { return IsBlocked (player); } return false; } bool IsRaidBlocked (string target) { var player = BasePlayer.Find (target); if (player is BasePlayer) { return IsBlocked (player); } return false; } bool IsCombatBlocked (string target) { var player = BasePlayer.Find (target); if (player is BasePlayer) { return IsBlocked (player); } return false; } bool ShouldBlockEscape (ulong target, ulong source, List sourceMembers = null) { if (target == source) { if ((ownerBlock || raiderBlock || blockAll) && (!ownerCheck)) return true; return false; } if (sourceMembers is List && sourceMembers.Contains (target.ToString ())) return false; return true; } //[ChatCommand ("bblocked")] //void cmdBBlocked (BasePlayer player, string command, string [] args) //{ // StartCombatBlocking (player); // StartRaidBlocking (player); //} //[ChatCommand ("bunblocked")] //void cmdBUnblocked (BasePlayer player, string command, string [] args) //{ // StopCombatBlocking (player); // StopRaidBlocking (player); //} void StartRaidBlocking (BasePlayer target, bool createZone = true) { StartRaidBlocking (target, target.transform.position, createZone); } void StartRaidBlocking (BasePlayer target, Vector3 position, bool createZone = true) { if (HasPerm (target.UserIDString, "disable")) { return; } if (target.gameObject == null) { return; } if (Interface.Call ("CanRaidBlock", target, position, createZone) != null) { return; } if (target.gameObject == null) return; var raidBlocker = target.gameObject.GetComponent (); if (raidBlocker == null) { raidBlocker = target.gameObject.AddComponent (); } Interface.CallHook ("OnRaidBlock", target, position); raidBlocker.lastBlock = DateTime.Now; if (raidBlockNotify) SendBlockMessage (target, raidBlocker, "Raid Block Notifier", "Raid Block Complete"); if (useZoneManager && createZone && (zoneEnter || zoneLeave)) CreateRaidZone (position); } void StartCombatBlocking (BasePlayer target) { if (HasPerm (target.UserIDString, "disable")) { return; } if (target.gameObject == null) { return; } if (Interface.Call ("CanCombatBlock", target) != null) { return; } var combatBlocker = target.gameObject.GetComponent (); if (combatBlocker == null) { combatBlocker = target.gameObject.AddComponent (); } Interface.CallHook ("OnCombatBlock", target); combatBlocker.lastBlock = DateTime.Now; if (combatBlockNotify) SendBlockMessage (target, combatBlocker, "Combat Block Notifier", "Combat Block Complete"); } void StopBlocking (BasePlayer target) { if (IsRaidBlocked (target)) StopBlocking (target); if (IsCombatBlocked (target)) StopBlocking (target); } public void StopBlocking (BasePlayer target) where T : BlockBehavior { if (target.gameObject == null) return; var block = target.gameObject.GetComponent (); if (block is BlockBehavior) block.Stop (); if (block is RaidBlock) { Interface.CallHook ("OnRaidBlockStopped", target); } else if (block is CombatBlock) { Interface.CallHook ("OnCombatBlockStopped", target); } } void ClearRaidBlockingS (string target) { StopRaidBlocking (target); } void StopRaidBlocking (BasePlayer player) { if (player is BasePlayer && IsRaidBlocked (player)) StopBlocking (player); } void StopRaidBlocking (string target) { var player = BasePlayer.Find (target); StopRaidBlocking (player); } void StopCombatBlocking (BasePlayer player) { if (player is BasePlayer && IsRaidBlocked (player)) StopBlocking (player); } void StopCombatBlocking (string target) { var player = BasePlayer.Find (target); StopCombatBlocking (player); } void ClearCombatBlocking (string target) { StopCombatBlocking (target); } #endregion #region Zone Handling void EraseZone (string zoneid) { ZoneManager.CallHook ("EraseZone", zoneid); zones.Remove (zoneid); } void ResetZoneTimer (RaidZone zone) { zone.ResetTimer ().timer = timer.In (raidDuration, delegate () { EraseZone (zone.zoneid); }); } void CreateRaidZone (Vector3 position) { var zoneid = position.ToString (); RaidZone zone; if (zones.TryGetValue (zoneid, out zone)) { ResetZoneTimer (zone); return; } foreach (var nearbyZone in zones) { if (nearbyZone.Value.Distance (position) < (raidDistance / 2)) { ResetZoneTimer (nearbyZone.Value); return; } } ZoneManager.CallHook ("CreateOrUpdateZone", zoneid, new string [] { "radius", raidDistance.ToString() }, position); zones.Add (zoneid, zone = new RaidZone (zoneid, position)); ResetZoneTimer (zone); } [HookMethod ("OnEnterZone")] void OnEnterZone (string zoneid, BasePlayer player) { if (!zoneEnter) return; if (!zones.ContainsKey (zoneid)) return; StartRaidBlocking (player, player.transform.position, false); } [HookMethod ("OnExitZone")] void OnExitZone (string zoneid, BasePlayer player) { if (!zoneLeave) return; if (!zones.ContainsKey (zoneid)) return; if (IsRaidBlocked (player)) { StopBlocking (player); } } [HookMethod ("OnPlayerEnteredRaidableBase")] void OnPlayerEnteredRaidableBase(BasePlayer player, Vector3 raidPos, bool allowPVP) { if (!raidableZoneEnter) return; StartRaidBlocking (player, false); } [HookMethod ("OnPlayerExitedRaidableBase")] void OnPlayerExitedRaidableBase(BasePlayer player, Vector3 raidPos, bool allowPVP) { if (!raidableZoneLeave) return; if (IsRaidBlocked (player)) { StopBlocking (player); } } #endregion #region Friend/Clan Integration public List getFriends (string player) { var players = new List (); if (player == null) return players; if (friendShare || friendCheck) { var friendList = getFriendList (player); if (friendList != null) players.AddRange (friendList); } if (clanShare || clanCheck) { var members = getClanMembers (player); if (members != null) players.AddRange (members); } return players; } public List getFriendList (string player) { object friends_obj = null; DateTime lastFriendCheckPlayer; var players = new List (); if (lastFriendCheck.TryGetValue (player, out lastFriendCheckPlayer)) { if ((DateTime.Now - lastFriendCheckPlayer).TotalMinutes <= cacheTimer && friendCache.TryGetValue (player, out players)) { return players; } else { friends_obj = Friends?.CallHook ("IsFriendOfS", player); lastFriendCheck [player] = DateTime.Now; } } else { friends_obj = Friends?.CallHook ("IsFriendOfS", player); lastFriendCheck.Add (player, DateTime.Now); } if (friends_obj == null) return players; string [] friends = friends_obj as string []; foreach (string fid in friends) players.Add (fid); if (friendCache.ContainsKey (player)) friendCache [player] = players; else friendCache.Add (player, players); return players; } public List getClanMembers (string player) { string tag = null; DateTime lastClanCheckPlayer; string lastClanCached; if (lastClanCheck.TryGetValue (player, out lastClanCheckPlayer) && clanCache.TryGetValue (player, out lastClanCached)) { if ((DateTime.Now - lastClanCheckPlayer).TotalMinutes <= cacheTimer) tag = lastClanCached; else { tag = Clans.Call ("GetClanOf", player); clanCache [player] = tag; lastClanCheck [player] = DateTime.Now; } } else { tag = Clans.Call ("GetClanOf", player); if (lastClanCheck.ContainsKey (player)) lastClanCheck.Remove (player); if (clanCache.ContainsKey (player)) clanCache.Remove (player); clanCache.Add (player, tag); lastClanCheck.Add (player, DateTime.Now); } if (tag == null) return null; List lastMemberCache; if (memberCache.TryGetValue (tag, out lastMemberCache)) return lastMemberCache; var clan = GetClan (tag); if (clan == null) return null; return CacheClan (clan); } JObject GetClan (string tag) { if (string.IsNullOrEmpty (tag)) { return null; } return Clans.Call ("GetClan", tag); } List CacheClan (JObject clan) { string tag = clan ["tag"].ToString (); List players = new List (); foreach (string memberid in clan ["members"]) { if (clanCache.ContainsKey (memberid)) clanCache [memberid] = tag; else clanCache.Add (memberid, tag); players.Add (memberid); } if (memberCache.ContainsKey (tag)) memberCache [tag] = players; else memberCache.Add (tag, players); if (lastCheck.ContainsKey (tag)) lastCheck [tag] = DateTime.Now; else lastCheck.Add (tag, DateTime.Now); return players; } [HookMethod ("OnClanCreate")] void OnClanCreate (string tag) { var clan = GetClan (tag); if (clan != null) { CacheClan (clan); } else { PrintWarning ("Unable to find clan after creation: " + tag); } } [HookMethod ("OnClanUpdate")] void OnClanUpdate (string tag) { var clan = GetClan (tag); if (clan != null) { CacheClan (clan); } else { PrintWarning ("Unable to find clan after update: " + tag); } } [HookMethod ("OnClanDestroy")] void OnClanDestroy (string tag) { if (lastCheck.ContainsKey (tag)) { lastCheck.Remove (tag); } if (memberCache.ContainsKey (tag)) { memberCache.Remove (tag); } } #endregion #region Permission Checking & External API Handling bool HasPerm (string userid, string perm) { return permission.UserHasPermission (userid, "noescape." + perm); } bool CanRaidCommand (BasePlayer player, string command) { return raidBlock && HasPerm (player.UserIDString, "raid." + command + "block") && IsRaidBlocked (player); } bool CanRaidCommand (string playerID, string command) { return raidBlock && HasPerm (playerID, "raid." + command + "block") && IsRaidBlocked (playerID); } bool CanCombatCommand (BasePlayer player, string command) { return combatBlock && HasPerm (player.UserIDString, "combat." + command + "block") && IsCombatBlocked (player); } bool CanCombatCommand (string playerID, string command) { return combatBlock && HasPerm (playerID, "combat." + command + "block") && IsCombatBlocked (playerID); } object CanDo (string command, BasePlayer player) { if (CanRaidCommand (player, command)) return GetMessage (player, "Raid Blocked Message", raidDuration); else if (CanCombatCommand (player, command)) return GetMessage (player, "Combat Blocked Message", combatDuration); return null; } object OnStructureRepair (BaseCombatEntity entity, BasePlayer player) { var result = CanDo ("repair", player); if (result is string) { if (entity.health > entity.MaxHealth ()) { return null; } SendReply (player, result.ToString ()); return true; } return null; } object OnStructureUpgrade (BuildingBlock block, BasePlayer player, BuildingGrade.Enum grade) { var result = CanDo ("upgrade", player); if (result is string) { SendReply (player, result.ToString ()); return true; } return null; } object CanRedeemKit (BasePlayer player) { return CanDo ("kit", player); } object CanUseMailbox (BasePlayer player, Mailbox mailbox) { var result = CanDo ("mailbox", player); if (result is string) { SendReply (player, result.ToString ()); return true; } return null; } object CanUseVending (VendingMachine machine, BasePlayer player) { var result = CanDo ("vend", player); if (result is string) { SendReply (player, result.ToString ()); return true; } return null; } object CanBuild (Planner plan, Construction prefab) { var player = plan.GetOwnerPlayer (); var result = CanDo ("build", player); if (result is string) { if (isEntityException (prefab.fullName)) { return null; } SendReply (player, result.ToString ()); return true; } return null; } object CanAssignBed (SleepingBag bag, BasePlayer player, ulong targetPlayerId) { var result = CanDo ("assignbed", player); if (result is string) { SendReply (player, result.ToString ()); return true; } return null; } object CanOpenBackpack(BasePlayer player, ulong backpackOwnerID) { return CanDo ("backpack", player); } object CanBank (BasePlayer player) { return CanDo ("bank", player); } object CanTrade (BasePlayer player) { return CanDo ("trade", player); } object canRemove (BasePlayer player) { return CanDo ("remove", player); } object canShop (BasePlayer player) { return CanDo ("shop", player); } object CanShop (BasePlayer player) { return CanDo ("shop", player); } object CanTeleport (BasePlayer player) { return CanDo ("tp", player); } object canTeleport (BasePlayer player) // ALIAS FOR MagicTeleportation { return CanTeleport (player); } object CanGridTeleport (BasePlayer player) // ALIAS FOR GrTeleport { return CanTeleport (player); } object CanCraft (ItemCrafter itemCrafter, ItemBlueprint bp, int amount) { BasePlayer player = itemCrafter.containers [0].GetOwnerPlayer (); if (player != null) { var result = CanDo ("craft", player); if (result is string) { SendReply (player, result.ToString ()); return false; } } return null; } object CanRecycleCommand (BasePlayer player) { return CanDo ("recycle", player); } object CanBGrade (BasePlayer player, int grade, BuildingBlock buildingBlock, Planner planner) { if (CanRaidCommand (player, "bgrade") || CanCombatCommand (player, "bgrade")) return -1; return null; } #endregion #region Messages void SendBlockMessage (BasePlayer target, BlockBehavior blocker, string langMessage, string completeMessage) { var send = false; if (blocker.lastNotification != DateTime.MinValue) { TimeSpan diff = DateTime.Now - blocker.lastNotification; if (diff.TotalSeconds >= (blocker.Duration / 2)) send = true; } else send = true; if (send) { string message = string.Empty; if (sendChatNotification || sendGUIAnnouncementsNotification) message = GetPrefix (target.UserIDString) + GetMsg (langMessage, target.UserIDString).Replace ("{time}", GetCooldownTime (blocker.Duration, target.UserIDString)); if (sendChatNotification) SendReply (target, message); if (sendGUIAnnouncementsNotification) GUIAnnouncements?.Call ("CreateAnnouncement", message, GUIAnnouncementTintColor, GUIAnnouncementTextColor, target); if (sendLustyMapNotification && LustyMapDuration > 0) { blocker.iconUID = Guid.NewGuid ().ToString ("N"); var obj = LustyMap?.Call ("AddMarker", target.transform.position.x, target.transform.position.z, blocker.iconUID, LustyMapIcon); if (obj is bool && (bool)obj == true) { timer.In (LustyMapDuration, delegate () { LustyMap?.Call ("RemoveMarker", blocker.iconUID); }); } } blocker.lastNotification = DateTime.Now; } blocker.Notify (delegate () { blocker.notifyCallback = null; if (target?.IsConnected == true) { string message = string.Empty; if (sendChatNotification || sendGUIAnnouncementsNotification) message = GetPrefix (target.UserIDString) + GetMsg (completeMessage, target.UserIDString); if (sendChatNotification) SendReply (target, message); if (sendGUIAnnouncementsNotification) GUIAnnouncements?.Call ("CreateAnnouncement", message, GUIAnnouncementTintColor, GUIAnnouncementTextColor, target); if (sendLustyMapNotification && LustyMapDuration > 0) LustyMap?.Call ("RemoveMarker", blocker.iconUID); } }); } string GetCooldownTime (float f, string userID) { if (f > 60) return Math.Round (f / 60, 1) + " " + GetMsg ("Unit Minutes", userID); return f + " " + GetMsg ("Unit Seconds", userID); } public string GetMessage (BasePlayer player) { if (IsRaidBlocked (player)) return GetMessage (player, "Raid Blocked Message", raidDuration); else if (IsCombatBlocked (player)) return GetMessage (player, "Combat Blocked Message", combatDuration); return null; } public string GetPrefix (string player) { string prefix = GetMsg ("Prefix", player); if (!string.IsNullOrEmpty (prefix)) { return prefix + ": "; } return string.Empty; } public string GetMessage (BasePlayer player, string blockMsg, float duration) where T : BlockBehavior { T blocker; if (duration > 0 && TryGetBlocker (player, out blocker)) { var ts = DateTime.Now - blocker.lastBlock; var unblocked = Math.Round ((duration / 60) - Convert.ToSingle (ts.TotalMinutes), 2); if (ts.TotalMinutes <= duration) { if (unblocked < 1) { var timelefts = Math.Round (Convert.ToDouble (duration) - ts.TotalSeconds); return GetPrefix (player.UserIDString) + GetMsg (blockMsg, player).Replace ("{time}", timelefts.ToString () + " " + GetMsg ("Unit Seconds", player)); } return GetPrefix (player.UserIDString) + GetMsg (blockMsg, player).Replace ("{time}", unblocked.ToString () + " " + GetMsg ("Unit Minutes", player)); } } return null; } #endregion #region Utility Methods bool TryGetBlocker (BasePlayer player, out T blocker) where T : BlockBehavior { blocker = null; if (player.gameObject == null) return false; if ((blocker = player.gameObject.GetComponent ()) != null) return true; return false; } public bool isEntityException (string prefabName) { var result = false; foreach (string p in exceptionPrefabs) { if (prefabName.IndexOf (p) != -1) { result = true; break; } } return result; } public bool IsEntityBlocked (BaseCombatEntity entity) { if (entity is BuildingBlock) { if (((BuildingBlock)entity).grade == BuildingGrade.Enum.Twigs) return false; return true; } var prefabName = entity.ShortPrefabName; var result = false; if (prefabBlockCache.TryGetValue (prefabName, out result)) return result; result = false; foreach (string p in blockedPrefabs) { if (prefabName.IndexOf (p) != -1) { result = true; break; } } prefabBlockCache.Add (prefabName, result); return result; } bool IsRaidDamage (DamageType dt) { return raidDamageTypes.Contains (dt.ToString ()); } bool IsDeathDamage (DamageType dt) { return raidDeathTypes.Contains (dt.ToString ()); } bool IsRaidDamage (DamageTypeList dtList) { for (int index = 0; index < dtList.types.Length; ++index) { if (dtList.types [index] > 0 && IsRaidDamage ((DamageType)index)) { return true; } } return false; } bool IsDeathDamage (DamageTypeList dtList) { for (int index = 0; index < dtList.types.Length; ++index) { if (dtList.types [index] > 0 && IsDeathDamage ((DamageType)index)) { return true; } } return false; } bool IsExcludedWeapon (string name) { if (string.IsNullOrEmpty (name)) { return false; } bool cachedValue; if (_cachedExcludedWeapons.TryGetValue (name, out cachedValue)) { return cachedValue; } foreach (var weaponName in exceptionWeapons) { if (name.Contains (weaponName)) { _cachedExcludedWeapons.Add (name, true); return true; } } _cachedExcludedWeapons.Add (name, false); return false; } bool IsCombatDamage (DamageType dt) { return combatDamageTypes.Contains (dt.ToString ()); } bool IsCombatDamage (DamageTypeList dtList) { for (int index = 0; index < dtList.types.Length; ++index) { if (dtList.types [index] > 0 && IsCombatDamage ((DamageType)index)) { return true; } } return false; } T GetConfig (string name, string name2, string name3, T defaultValue) { try { var val = Config [name, name2, name3]; return ParseValue (val, defaultValue); } catch (Exception ex) { //PrintWarning ("Invalid config value: " + name + "/" + name2 + "/" + name3 + " (" + ex.Message + ")"); Config [name, name2, name3] = defaultValue; Config.Save (); return defaultValue; } } T GetConfig (string name, string name2, T defaultValue) { try { var val = Config [name, name2]; return ParseValue (val, defaultValue); } catch (Exception ex) { //PrintWarning ("Invalid config value: " + name + "/" + name2 + " (" + ex.Message + ")"); Config [name, name2] = defaultValue; Config.Save (); return defaultValue; } } T GetConfig (string name, T defaultValue) { try { var val = Config [name]; return ParseValue (val, defaultValue); } catch (Exception ex) { //PrintWarning ("Invalid config value: " + name + " (" + ex.Message + ")"); Config [name] = defaultValue; Config.Save (); return defaultValue; } } T ParseValue (object val, T defaultValue) { if (val == null) return defaultValue; if (val is List) { var t = typeof (T).GetGenericArguments () [0]; if (t == typeof (String)) { var cval = new List (); foreach (var v in val as List) cval.Add ((string)v); val = cval; } else if (t == typeof (int)) { var cval = new List (); foreach (var v in val as List) cval.Add (Convert.ToInt32 (v)); val = cval; } } else if (val is Dictionary) { var t = typeof (T).GetGenericArguments () [1]; if (t == typeof (int)) { var cval = new Dictionary (); foreach (var v in val as Dictionary) cval.Add (Convert.ToString (v.Key), Convert.ToInt32 (v.Value)); val = cval; } } return (T)Convert.ChangeType (val, typeof (T)); } static string GetMsg (string key, object user = null) { if (user is BasePlayer) { user = ((BasePlayer)user).UserIDString; } return plugin.lang.GetMessage (key, plugin, user == null ? null : user.ToString ()); } #endregion } }