Help Required

yes, change it to

if (player == null)​

Done. Scientists still not dealing damage. Also players aren't able to damage themselves either

then you didn't edit it correctly :p

my example got reverted some how

change

if (player == null || player.IsNpc)
    return;​

to

if (player == null)
    return;​


don't remove anything else, especially not return;

Yep I have done that.

using Facepunch;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Zone Manager", "k1lly0u", "3.0.91")]
    [Description("An advanced management system for creating in-game zones")]
    public class ZoneManager : RustPlugin
    {
        #region Fields
        [PluginReference] Plugin Backpacks, PopupNotifications, Spawns;

        private StoredData storedData;

        private DynamicConfigFile data;

        private Hash<string, Zone> zones = new Hash<string, Zone>();

        private Hash<ulong, EntityZones> zonedPlayers = new Hash<ulong, EntityZones>();

        private Hash<uint, EntityZones> zonedEntities = new Hash<uint, EntityZones>();

        private Dictionary<ulong, string> lastPlayerZone = new Dictionary<ulong, string>();


        private ZoneFlags globalFlags;

        private bool zonesInitialized = false;


        private static ZoneManager Instance { get; set; }

        private const string PERMISSION_ZONE = "zonemanager.zone";

        private const string PERMISSION_IGNORE_FLAG = "zonemanager.ignoreflag.";

        private const int PLAYER_MASK = 131072;

        private const int TARGET_LAYERS = ~(1 << 10 | 1 << 18 | 1 << 28 | 1 << 29);
        #endregion

        #region Oxide Hooks
        private void Loaded()
        {
            lang.RegisterMessages(Messages, this);

            data = Interface.Oxide.DataFileSystem.GetFile("ZoneManager/zone_data");
            data.Settings.Converters = new JsonConverter[] { new StringEnumConverter(), new Vector3Converter() };

            permission.RegisterPermission(PERMISSION_ZONE, this);

            foreach (object flag in Enum.GetValues(typeof(ZoneFlags)))
                permission.RegisterPermission(PERMISSION_IGNORE_FLAG + flag.ToString().ToLower(), this);

            Instance = this;

            LoadData();
        }

        private void OnServerInitialized()
        {
            InitializeZones();
            InitializeUpdateBehaviour();
        }

        private void OnTerrainInitialized() => InitializeZones();

        private void OnPlayerConnected(BasePlayer player) => updateBehaviour.QueueUpdate(player);

        private void OnEntityKill(BaseEntity baseEntity)
        {
            if (baseEntity == null || !baseEntity.IsValid() || baseEntity.IsDestroyed)
                return;

            EntityZones entityZones;
            if (zonedEntities.TryGetValue(baseEntity.net.ID, out entityZones))
            {
                for (int i = entityZones.Zones.Count - 1; i >= 0; i--)
                {
                    entityZones.Zones.ElementAt(i)?.OnEntityExitZone(baseEntity, false, true);
                }

                zonedEntities.Remove(baseEntity.net.ID);
            }
        }

        private void Unload()
        {
            DestroyUpdateBehaviour();

            foreach (BasePlayer player in BasePlayer.activePlayerList)
                CuiHelper.DestroyUi(player, ZMUI);

            foreach (KeyValuePair<string, Zone> kvp in zones)
                UnityEngine.Object.Destroy(kvp.Value.gameObject);

            zones.Clear();

            Instance = null;
        }
        #endregion

        #region UpdateQueue  
        private UpdateBehaviour updateBehaviour;

        private void InitializeUpdateBehaviour()
        {
            updateBehaviour = new GameObject("ZoneManager.UpdateBehaviour").AddComponent<UpdateBehaviour>();

            foreach (BasePlayer player in BasePlayer.activePlayerList)
                updateBehaviour.QueueUpdate(player);
        }

        private void DestroyUpdateBehaviour() => UnityEngine.Object.Destroy(updateBehaviour?.gameObject);

        // Queue and check players for new zones and that they are still in old zones. Previously any plugin that put a player to sleep and teleports them out of a zone
        // without calling the OnPlayerSleep hook would bypass a player zone update which would result in players being registered in zones they were no longer in.
        // Options are to either continually check and update players, or have every plugin that teleports players call the hook...
        private class UpdateBehaviour : MonoBehaviour
        {
            private System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

            private Queue<BasePlayer> playerUpdateQueue = new Queue<BasePlayer>();

            private const float MAX_MS = 0.25f;

            private void OnDestroy()
            {
                playerUpdateQueue.Clear();
            }

            internal void QueueUpdate(BasePlayer player)
            {
                if (!playerUpdateQueue.Contains(player))
                    playerUpdateQueue.Enqueue(player);
            }

            private void Update()
            {
                if (Time.frameCount % 10 != 0)
                    return;

                sw.Reset();
                sw.Start();

                while (playerUpdateQueue.Count > 0)
                {
                    if (sw.Elapsed.TotalMilliseconds >= MAX_MS)
                    {
                        sw.Stop();
                        return;
                    }

                    BasePlayer player = playerUpdateQueue.Dequeue();
                    if (player == null || !player.IsConnected)
                        continue;

                    Instance.UpdatePlayerZones(player);

                    InvokeHandler.Invoke(this, () => QueueUpdate(player), 2f);
                }
            }
        }
        #endregion

        #region Flag Hooks
        private void OnEntityBuilt(Planner planner, GameObject gObject)
        {
            BasePlayer player = planner?.GetOwnerPlayer();
            if (player == null)
                return;

            BaseEntity entity = gObject?.ToBaseEntity();
            if (entity == null)
                return;

            if (entity is BuildingBlock || entity is SimpleBuildingBlock)
            {
                if (HasPlayerFlag(player, ZoneFlags.NoBuild, true))
                {
                    entity.Invoke(() => entity.Kill(BaseNetworkable.DestroyMode.Gib), 0.1f);
                    SendMessage(player, Message("noBuild", player.UserIDString));
                }
            }
            else
            {
                if (entity is BuildingPrivlidge)
                {
                    if (HasPlayerFlag(player, ZoneFlags.NoCup, false))
                    {
                        entity.Invoke(() => entity.Kill(BaseNetworkable.DestroyMode.Gib), 0.1f);
                        SendMessage(player, Message("noCup", player.UserIDString));
                    }
                }
                else
                {
                    if (HasPlayerFlag(player, ZoneFlags.NoDeploy, true))
                    {
                        entity.Invoke(() => entity.Kill(BaseNetworkable.DestroyMode.Gib), 0.1f);
                        SendMessage(player, Message("noDeploy", player.UserIDString));
                    }
                }
            }
        }

        private object OnStructureUpgrade(BuildingBlock buildingBlock, BasePlayer player, BuildingGrade.Enum grade)
        {
            if (HasPlayerFlag(player, ZoneFlags.NoUpgrade, true))
            {
                SendMessage(player, Message("noUpgrade", player.UserIDString));
                return true;
            }
            return null;
        }

        private void OnItemDeployed(Deployer deployer, BaseEntity deployedEntity)
        {
            BasePlayer player = deployer.GetOwnerPlayer();
            if (player == null)
                return;

            if (HasPlayerFlag(player, ZoneFlags.NoDeploy, true))
            {
                deployedEntity.Invoke(() => deployedEntity.Kill(BaseNetworkable.DestroyMode.Gib), 0.1f);
                SendMessage(player, Message("noDeploy", player.UserIDString));
            }
        }

        private void OnItemUse(Item item, int amount)
        {
            BaseEntity entity = item?.parent?.entityOwner;
            if (entity == null)
                return;

            if (entity is FlameTurret || entity is AutoTurret || entity is GunTrap)
            {
                if (HasEntityFlag(entity, ZoneFlags.InfiniteTrapAmmo))
                    item.amount += amount;
                return;
            }

            if (entity is SearchLight)
            {
                if (HasEntityFlag(entity, ZoneFlags.AlwaysLights))
                {
                    item.amount += amount;
                    return;
                }

                if (HasEntityFlag(entity, ZoneFlags.AutoLights))
                {
                    if (TOD_Sky.Instance.Cycle.Hour > Instance.configData.AutoLights.OnTime || TOD_Sky.Instance.Cycle.Hour < Instance.configData.AutoLights.OffTime)
                        item.amount += amount;
                }
            }
        }

        private void OnRunPlayerMetabolism(PlayerMetabolism metabolism, BaseCombatEntity ownerEntity, float delta)
        {
            BasePlayer player = ownerEntity as BasePlayer;
            if (player == null)
                return;

            if (metabolism.bleeding.value > 0 && HasPlayerFlag(player, ZoneFlags.NoBleed, false))
                metabolism.bleeding.value = 0f;
            if (metabolism.oxygen.value < 1 && HasPlayerFlag(player, ZoneFlags.NoDrown, false))
                metabolism.oxygen.value = 1f;
        }

        private object OnPlayerChat(BasePlayer player, string message, ConVar.Chat.ChatChannel channel)
        {
            if (player == null)
                return null;

            if (HasPlayerFlag(player, ZoneFlags.NoChat, true))
            {
                SendMessage(player, Message("noChat", player.UserIDString));
                return true;
            }
            return null;
        }

        private object OnBetterChat(Oxide.Core.Libraries.Covalence.IPlayer iPlayer, string message)
        {
            BasePlayer player = iPlayer.Object as BasePlayer;
            return OnPlayerChat(player, message, ConVar.Chat.ChatChannel.Global);
        }

        private object OnPlayerVoice(BasePlayer player, Byte[] data)
        {
            if (HasPlayerFlag(player, ZoneFlags.NoVoice, true))
            {
                SendMessage(player, Message("noVoice", player.UserIDString));
                return true;
            }
            return null;
        }

        private object OnServerCommand(ConsoleSystem.Arg arg)
        {
            BasePlayer player = arg.Player();
            if (player == null || arg.cmd?.Name == null)
                return null;

            if (arg.cmd.Name == "kill" && HasPlayerFlag(player, ZoneFlags.NoSuicide, false))
            {
                SendMessage(player, Message("noSuicide", player.UserIDString));
                return true;
            }
            return null;
        }

        private void OnPlayerDisconnected(BasePlayer player)
        {
            if (player == null)
                return;

            if (HasPlayerFlag(player, ZoneFlags.KillSleepers, true))
            {
                player.Die();
                return;
            }

            if (HasPlayerFlag(player, ZoneFlags.EjectSleepers, true))
            {
                EntityZones entityZones;
                if (!zonedPlayers.TryGetValue(player.userID, out entityZones) || entityZones.Count == 0)
                    return;

                for (int i = 0; i < entityZones.Count; i++)
                {
                    Zone zone = entityZones.Zones.ElementAt(i);
                    if (zone == null)
                        continue;

                    if (HasFlag(zone, ZoneFlags.EjectSleepers))
                    {
                        EjectPlayer(player, zone);
                        return;
                    }
                }
            }
        }

        private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo hitinfo)
        {
            if (entity == null || entity.GetComponent<ResourceDispenser>() != null)
                return null;

            BasePlayer attacker = hitinfo.InitiatorPlayer;
            BasePlayer victim = entity as BasePlayer;

            if (victim != null)
            {
                if (hitinfo.damageTypes.GetMajorityDamageType() == DamageType.Fall)
                {
                    if (HasPlayerFlag(victim, ZoneFlags.NoFallDamage, false))
                        return true;
                }

                if (victim.IsSleeping() && HasPlayerFlag(victim, ZoneFlags.SleepGod, false))
                    return true;
                else if (attacker != null)
                {
                    if (victim.IsNpc)
                        return null;

                    if (HasPlayerFlag(victim, ZoneFlags.PvpGod, false))
                    {
                        if (attacker == victim && hitinfo.damageTypes.GetMajorityDamageType() == DamageType.Suicide)
                        {
                            if (HasPlayerFlag(victim, ZoneFlags.NoSuicide, false))
                                return true;
                            return null;
                        }
                        if (attacker.IsNpc && configData.NPCHurtPvpGod)
                            return null;

                        return true;
                    }
                    else if (HasPlayerFlag(attacker, ZoneFlags.PvpGod, false) && !attacker.IsNpc)                    
                        return true;                    
                }
                else if (HasPlayerFlag(victim, ZoneFlags.PveGod, false) && !victim.IsNpc)
                    return true;
                else if (hitinfo.Initiator is FireBall && HasPlayerFlag(victim, ZoneFlags.PvpGod, false))
                    return true;
                return null;
            }

            BaseNpc baseNpc = entity as BaseNpc;
            if (baseNpc != null)
            {
                if (HasEntityFlag(baseNpc, ZoneFlags.NoPve))
                {
                    if (attacker != null && CanBypass(attacker, ZoneFlags.NoPve))
                        return null;
                    return true;
                }
                return null;
            }

            if (!(entity is LootContainer) && !(entity is BaseHelicopter))
            {
                if (HasEntityFlag(entity, ZoneFlags.UnDestr))
                {
                    if (hitinfo.InitiatorPlayer != null && CanBypass(hitinfo.InitiatorPlayer, ZoneFlags.UnDestr))
                        return null;

                    if (hitinfo.damageTypes.GetMajorityDamageType() == DamageType.Decay && configData.DecayDamageUndestr)
                        return null;

                    return true;
                }
            }

            return null;
        }

        private void OnEntitySpawned(BaseNetworkable baseNetworkable)
        {
            if (baseNetworkable is BaseEntity)
                timer.In(2, () => CanSpawn(baseNetworkable as BaseEntity));
        }

        private void CanSpawn(BaseEntity baseEntity)
        {
            if (!baseEntity.IsValid() || baseEntity.IsDestroyed)
                return;

            if (Interface.CallHook("CanSpawnInZone", baseEntity) != null)
                return;

            if (baseEntity is BaseCorpse)
            {
                if (HasEntityFlag(baseEntity, ZoneFlags.NoCorpse) && !CanBypass((baseEntity as BaseCorpse).OwnerID, ZoneFlags.NoCorpse))
                    baseEntity.Invoke(() => baseEntity.Kill(BaseNetworkable.DestroyMode.None), 0.1f);
            }
            if (baseEntity is LootContainer || baseEntity is JunkPile)
            {
                if (HasEntityFlag(baseEntity, ZoneFlags.NoLootSpawns))
                    baseEntity.Invoke(() => baseEntity.Kill(BaseNetworkable.DestroyMode.None), 0.1f);
            }
            else if (baseEntity is BaseNpc || baseEntity is NPCPlayer)
            {
                if (HasEntityFlag(baseEntity, ZoneFlags.NoNPCSpawns))
                    baseEntity.Invoke(() => baseEntity.Kill(BaseNetworkable.DestroyMode.None), 0.1f);
            }
            else if (baseEntity is DroppedItem || baseEntity is WorldItem)
            {
                if (HasEntityFlag(baseEntity, ZoneFlags.NoDrop))
                {
                    (baseEntity as WorldItem).item.Remove(0f);
                    baseEntity.Invoke(() => baseEntity.Kill(BaseNetworkable.DestroyMode.None), 0.1f);
                }
            }
            else if (baseEntity is DroppedItemContainer)
            {
                if (HasEntityFlag(baseEntity, ZoneFlags.NoDrop))
                    baseEntity.Invoke(() => baseEntity.Kill(BaseNetworkable.DestroyMode.None), 0.1f);
            }
        }

        private object CanBeWounded(BasePlayer player, HitInfo hitinfo) => HasPlayerFlag(player, ZoneFlags.NoWounded, false) ? (object)false : null;

        private object CanUpdateSign(BasePlayer player, Signage sign)
        {
            if (HasPlayerFlag(player, ZoneFlags.NoSignUpdates, false))
            {
                SendMessage(player, Message("noSignUpdates", player.UserIDString));
                return false;
            }
            return null;
        }

        private object OnOvenToggle(BaseOven oven, BasePlayer player)
        {
            if (HasPlayerFlag(player, ZoneFlags.NoOvenToggle, false))
            {
                SendMessage(player, Message("noOvenToggle", player.UserIDString));
                return true;
            }
            return null;
        }

        private object CanUseVending(BasePlayer player, VendingMachine machine)
        {
            if (HasPlayerFlag(player, ZoneFlags.NoVending, false))
            {
                SendMessage(player, Message("noVending", player.UserIDString));
                return false;
            }
            return null;
        }

        private object CanHideStash(BasePlayer player, StashContainer stash)
        {
            if (HasPlayerFlag(player, ZoneFlags.NoStash, false))
            {
                SendMessage(player, Message("noStash", player.UserIDString));
                return false;
            }
            return null;
        }

        private object CanCraft(ItemCrafter itemCrafter, ItemBlueprint bp, int amount)
        {
            BasePlayer player = itemCrafter.GetComponent<BasePlayer>();
            if (player != null)
            {
                if (HasPlayerFlag(player, ZoneFlags.NoCraft, false))
                {
                    SendMessage(player, Message("noCraft", player.UserIDString));
                    return false;
                }
            }
            return null;
        }

        private void OnDoorOpened(Door door, BasePlayer player)
        {
            if (HasPlayerFlag(player, ZoneFlags.NoDoorAccess, false))
            {
                SendMessage(player, Message("noDoor", player.UserIDString));
                door.CloseRequest();
            }
        }

        #region Looting Hooks
        private object CanLootPlayer(BasePlayer target, BasePlayer looter) => OnLootPlayerInternal(looter, target);

        private void OnLootPlayer(BasePlayer looter, BasePlayer target) => OnLootPlayerInternal(looter, target);

        private object OnLootPlayerInternal(BasePlayer looter, BasePlayer target)
        {
            if (HasPlayerFlag(looter, ZoneFlags.NoPlayerLoot, false) || (target != null && HasPlayerFlag(target, ZoneFlags.NoPlayerLoot, false)))
            {
                if (looter == target && Backpacks != null)
                {
                    object hookResult = Backpacks.Call("CanLootPlayer", target, looter);
                    if (hookResult is bool && (bool)hookResult)
                        return true;
                }

                SendMessage(looter, Message("noLoot", looter.UserIDString));
                NextTick(looter.EndLooting);
                return false;
            }
            return null;
        }

        private void OnLootEntity(BasePlayer player, BaseEntity entity)
        {
            if (entity is LootableCorpse)
                OnLootCorpse(entity as LootableCorpse, player);
            if (entity is DroppedItemContainer)
                OnLootContainer(entity as DroppedItemContainer, player);
            if (entity is StorageContainer)
                OnLootInternal(player, ZoneFlags.NoBoxLoot);
        }

        private object CanLootEntity(BasePlayer player, LootableCorpse corpse)
        {
            if (corpse.playerSteamID == player.userID && HasPlayerFlag(player, ZoneFlags.LootSelf, false))
                return null;
            return CanLootInternal(player, ZoneFlags.NoPlayerLoot);
        }

        private void OnLootCorpse(LootableCorpse corpse, BasePlayer player)
        {
            if (corpse.playerSteamID == player.userID && HasPlayerFlag(player, ZoneFlags.LootSelf, false))
                return;

            OnLootInternal(player, ZoneFlags.NoPlayerLoot);
        }

        private void OnLootContainer(DroppedItemContainer container, BasePlayer player)
        {
            if (container.playerSteamID == player.userID && HasPlayerFlag(player, ZoneFlags.LootSelf, false))
                return;

            OnLootInternal(player, ZoneFlags.NoPlayerLoot);
        }

        private object CanLootEntity(BasePlayer player, DroppedItemContainer container)
        {
            if (container.playerSteamID == player.userID && HasPlayerFlag(player, ZoneFlags.LootSelf, false))
                return null;

            return CanLootInternal(player, ZoneFlags.NoPlayerLoot);
        }

        private object CanLootEntity(BasePlayer player, StorageContainer container) => CanLootInternal(player, ZoneFlags.NoBoxLoot);

        private object CanLootInternal(BasePlayer player, ZoneFlags flag)
        {
            if (HasPlayerFlag(player, flag, false))
            {
                SendMessage(player, Message("noLoot", player.UserIDString));
                return false;
            }
            return null;
        }

        private void OnLootInternal(BasePlayer player, ZoneFlags flag)
        {
            if (HasPlayerFlag(player, flag, false))
            {
                SendMessage(player, Message("noLoot", player.UserIDString));
                NextTick(player.EndLooting);
            }
        }
        #endregion

        #region Pickup Hooks
        private object CanPickupEntity(BasePlayer player, BaseCombatEntity entity) => CanPickupInternal(player, ZoneFlags.NoEntityPickup);

        private object CanPickupLock(BasePlayer player, BaseLock baseLock) => CanPickupInternal(player, ZoneFlags.NoEntityPickup);

        private object OnItemPickup(Item item, BasePlayer player) => CanPickupInternal(player, ZoneFlags.NoPickup);

        private object CanPickupInternal(BasePlayer player, ZoneFlags flag)
        {
            if (HasPlayerFlag(player, flag, false))
            {
                SendMessage(player, Message("noPickup", player.UserIDString));
                return false;
            }
            return null;
        }
        #endregion

        #region Gather Hooks        
        private object CanLootEntity(ResourceContainer container, BasePlayer player) => OnGatherInternal(player);

        private object OnCollectiblePickup(Item item, BasePlayer player) => OnGatherInternal(player);

        private object OnGrowableGather(GrowableEntity plant, Item item, BasePlayer player) => OnGatherInternal(player);

        private object OnDispenserGather(ResourceDispenser dispenser, BaseEntity entity, Item item) => OnGatherInternal(entity?.ToPlayer());

        private object OnGatherInternal(BasePlayer player)
        {
            if (player != null)
            {
                if (HasPlayerFlag(player, ZoneFlags.NoGather, false))
                {
                    SendMessage(player, Message("noGather", player.UserIDString));
                    return true;
                }
            }
            return null;
        }
        #endregion

        #region Targeting Hooks
        private object OnTurretTarget(AutoTurret turret, BaseCombatEntity entity) => OnTargetPlayerInternal(entity?.ToPlayer(), ZoneFlags.NoTurretTargeting);

        private object CanBradleyApcTarget(BradleyAPC apc, BaseEntity entity)
        {
            if (HasPlayerFlag(entity?.ToPlayer(), ZoneFlags.NoAPCTargeting, false))
                return false;
            return null;
        }

        private object CanHelicopterTarget(PatrolHelicopterAI heli, BasePlayer player)
        {
            if (HasPlayerFlag(player, ZoneFlags.NoHeliTargeting, false))
            {
                heli.interestZoneOrigin = heli.GetRandomPatrolDestination();
                return false;
            }
            return null;
        }

        private object CanHelicopterStrafeTarget(PatrolHelicopterAI heli, BasePlayer player)
        {
            if (HasPlayerFlag(player, ZoneFlags.NoHeliTargeting, false))
                return false;
            return null;
        }

        private object OnHelicopterTarget(HelicopterTurret turret, BaseCombatEntity entity) => OnTargetPlayerInternal(entity?.ToPlayer(), ZoneFlags.NoHeliTargeting);

        private object OnNpcTarget(BaseCombatEntity entity, BasePlayer player) => OnTargetPlayerInternal(player, ZoneFlags.NoNPCTargeting);

        private object OnTargetPlayerInternal(BasePlayer player, ZoneFlags flag)
        {
            if (player != null)
            {
                if (HasPlayerFlag(player, flag, false))
                    return true;
            }
            return null;
        }
        #endregion

        #region Additional KillSleeper Checks
        private void OnPlayerSleep(BasePlayer player)
        {
            if (player == null)
                return;

            //player.Invoke(()=> UpdatePlayerZones(player), 1f); // Manually update the zones a player is in. Sleeping players don't trigger OnTriggerEnter or OnTriggerExit            

            timer.In(2f, () =>
            {
                if (player == null || !player.IsSleeping())
                    return;

                if (!player.IsConnected)
                {
                    if (HasPlayerFlag(player, ZoneFlags.KillSleepers, true))
                    {
                        player.Invoke(() => KillSleepingPlayer(player), 3f);
                        return;
                    }

                    if (HasPlayerFlag(player, ZoneFlags.EjectSleepers, true))
                    {
                        player.Invoke(() =>
                        {
                            if (player == null || !player.IsSleeping())
                                return;

                            EntityZones entityZones;
                            if (!zonedPlayers.TryGetValue(player.userID, out entityZones) || entityZones.Count == 0)
                                return;

                            for (int i = 0; i < entityZones.Count; i++)
                            {
                                Zone zone = entityZones.Zones.ElementAt(i);
                                if (zone == null)
                                    return;

                                if (HasFlag(zone, ZoneFlags.EjectSleepers))
                                {
                                    EjectPlayer(player, zone);
                                }
                            }
                        }, 3f);
                    }
                }
            });
        }

        private void OnPlayerSleepEnd(BasePlayer player) => updateBehaviour.QueueUpdate(player);

        private void KillSleepingPlayer(BasePlayer player)
        {
            if (player == null || !player.IsSleeping())
                return;

            if (HasPlayerFlag(player, ZoneFlags.KillSleepers, true))
            {
                if (player.IsConnected)
                    OnPlayerSleep(player);
                else player.Die();
            }
        }

        private void UpdatePlayerZones(BasePlayer player)
        {
            if (player == null)
                return;

            EntityZones entityZones;
            if (zonedPlayers.TryGetValue(player.userID, out entityZones))
            {
                for (int i = entityZones.Count - 1; i >= 0; i--)
                {
                    Zone zone = entityZones.Zones.ElementAt(i);
                    if (zone == null)
                        continue;

                    if (zone.definition.Size != Vector3.zero)
                    {
                        if (!IsInsideBounds(zone, player.transform.position))
                            OnPlayerExitZone(player, zone);
                    }
                    else
                    {
                        if (Vector3.Distance(player.transform.position, zone.transform.position) > zone.definition.Radius)
                            OnPlayerExitZone(player, zone);
                    }
                }
            }

            for (int i = 0; i < zones.Count; i++)
            {
                Zone zone = zones.ElementAt(i).Value;
                if (zone == null)
                    continue;

                if (entityZones != null && entityZones.Zones.Contains(zone))
                    continue;

                if (zone.definition.Size != Vector3.zero)
                {
                    if (IsInsideBounds(zone, player.transform.position))
                        OnPlayerEnterZone(player, zone);
                }
                else
                {
                    if (Vector3.Distance(player.transform.position, zone.transform.position) <= zone.definition.Radius)
                        OnPlayerEnterZone(player, zone);
                }
            }

            if (player.HasPlayerFlag(BasePlayer.PlayerFlags.SafeZone) && !player.InSafeZone())
                player.SetPlayerFlag(BasePlayer.PlayerFlags.SafeZone, false);
        }

        private bool IsInsideBounds(Zone zone, Vector3 worldPos) => zone?.collider?.ClosestPoint(worldPos) == worldPos;
        #endregion
        #endregion

        #region Zone Functions
        private void InitializeZones()
        {
            if (zonesInitialized)
                return;

            foreach (Zone.Definition definition in storedData.definitions)
                CreateZone(definition);

            foreach (Zone zone in zones.Values)
                zone.FindZoneParent();

            zonesInitialized = true;

            UnsubscribeAll();
            UpdateHookSubscriptions();
        }

        private void CreateZone(Zone.Definition definition)
        {
            Zone zone = new GameObject().AddComponent<Zone>();
            zone.InitializeZone(definition);

            zones.Add(definition.Id, zone);
        }

        private bool ReverseVelocity(BasePlayer player)
        {
            BaseVehicle baseVehicle = player.GetMounted().VehicleParent();
            if (baseVehicle != null)
            {
                Vector3 euler = baseVehicle.transform.eulerAngles;
                baseVehicle.transform.rotation = Quaternion.Euler(euler.x, euler.y - 180f, euler.z);
                baseVehicle.rigidBody.velocity *= -1f;
                return true;
            }
            return false;
        }

        private void EjectPlayer(BasePlayer player, Zone zone)
        {
            if (zone.keepInList.Contains(player.userID) || zone.whitelist.Contains(player.userID))
                return;

            if (!string.IsNullOrEmpty(zone.definition.Permission))
            {
                if (HasPermission(player, zone.definition.Permission))
                    return;
            }

            if (player.isMounted && ReverseVelocity(player))
            {
                SendMessage(player, Message("eject", player.UserIDString));
                return;
            }

            Vector3 position = Vector3.zero;
            if (Spawns && !string.IsNullOrEmpty(zone.definition.EjectSpawns))
            {
                object success = Spawns.Call("GetRandomSpawn", zone.definition.EjectSpawns);
                if (success is Vector3)
                    position = (Vector3)success;
            }

            if (position == Vector3.zero)
            {
                float distance;
                if (zone.definition.Size != Vector3.zero)
                    distance = Mathf.Max(zone.definition.Size.x, zone.definition.Size.z);
                else distance = zone.definition.Radius;

                position = zone.transform.position + (((player.transform.position.XZ3D() - zone.transform.position.XZ3D()).normalized) * (distance + 10f));

                RaycastHit rayHit;
                if (Physics.Raycast(new Ray(new Vector3(position.x, position.y + 300, position.z), Vector3.down), out rayHit, 500, TARGET_LAYERS, QueryTriggerInteraction.Ignore))
                    position.y = rayHit.point.y;
                else position.y = TerrainMeta.HeightMap.GetHeight(position);
            }

            player.MovePosition(position);
            player.ClientRPCPlayer(null, player, "ForcePositionTo", player.transform.position);
            player.SendNetworkUpdateImmediate();

            SendMessage(player, Message("eject", player.UserIDString));
        }

        private void AttractPlayer(BasePlayer player, Zone zone)
        {
            if (player.isMounted && ReverseVelocity(player))
            {
                SendMessage(player, Message("attract", player.UserIDString));
                return;
            }

            float distance;
            if (zone.definition.Size != Vector3.zero)
                distance = Mathf.Max(zone.definition.Size.x, zone.definition.Size.z);
            else distance = zone.definition.Radius;

            Vector3 position = zone.transform.position + (player.transform.position - zone.transform.position).normalized * (distance - 5f);
            position.y = TerrainMeta.HeightMap.GetHeight(position);

            player.MovePosition(position);
            player.ClientRPCPlayer(null, player, "ForcePositionTo", player.transform.position);
            player.SendNetworkUpdateImmediate();

            SendMessage(player, Message("attract", player.UserIDString));
        }

        private void ShowZone(BasePlayer player, string zoneId, float time = 30)
        {
            Zone zone = GetZoneByID(zoneId);
            if (zone == null)
                return;

            if (zone.definition.Size != Vector3.zero)
            {
                Vector3 center = zone.definition.Location;
                Quaternion rotation = Quaternion.Euler(zone.definition.Rotation);
                Vector3 size = zone.definition.Size / 2;
                Vector3 point1 = RotatePointAroundPivot(new Vector3(center.x + size.x, center.y + size.y, center.z + size.z), center, rotation);
                Vector3 point2 = RotatePointAroundPivot(new Vector3(center.x + size.x, center.y - size.y, center.z + size.z), center, rotation);
                Vector3 point3 = RotatePointAroundPivot(new Vector3(center.x + size.x, center.y + size.y, center.z - size.z), center, rotation);
                Vector3 point4 = RotatePointAroundPivot(new Vector3(center.x + size.x, center.y - size.y, center.z - size.z), center, rotation);
                Vector3 point5 = RotatePointAroundPivot(new Vector3(center.x - size.x, center.y + size.y, center.z + size.z), center, rotation);
                Vector3 point6 = RotatePointAroundPivot(new Vector3(center.x - size.x, center.y - size.y, center.z + size.z), center, rotation);
                Vector3 point7 = RotatePointAroundPivot(new Vector3(center.x - size.x, center.y + size.y, center.z - size.z), center, rotation);
                Vector3 point8 = RotatePointAroundPivot(new Vector3(center.x - size.x, center.y - size.y, center.z - size.z), center, rotation);

                player.SendConsoleCommand("ddraw.line", time, Color.blue, point1, point2);
                player.SendConsoleCommand("ddraw.line", time, Color.blue, point1, point3);
                player.SendConsoleCommand("ddraw.line", time, Color.blue, point1, point5);
                player.SendConsoleCommand("ddraw.line", time, Color.blue, point4, point2);
                player.SendConsoleCommand("ddraw.line", time, Color.blue, point4, point3);
                player.SendConsoleCommand("ddraw.line", time, Color.blue, point4, point8);

                player.SendConsoleCommand("ddraw.line", time, Color.blue, point5, point6);
                player.SendConsoleCommand("ddraw.line", time, Color.blue, point5, point7);
                player.SendConsoleCommand("ddraw.line", time, Color.blue, point6, point2);
                player.SendConsoleCommand("ddraw.line", time, Color.blue, point8, point6);
                player.SendConsoleCommand("ddraw.line", time, Color.blue, point8, point7);
                player.SendConsoleCommand("ddraw.line", time, Color.blue, point7, point3);
            }
            else player.SendConsoleCommand("ddraw.sphere", time, Color.blue, zone.definition.Location, zone.definition.Radius);
        }

        private Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Quaternion rotation) => rotation * (point - pivot) + pivot;

        #endregion

        #region Component
        public class Zone : MonoBehaviour
        {
            internal Definition definition;

            internal ZoneFlags disabledFlags = ZoneFlags.None;

            internal Zone parent;

            internal List<BasePlayer> players = Pool.GetList<BasePlayer>();

            internal List<BaseEntity> entities = Pool.GetList<BaseEntity>();

            internal List<ulong> keepInList = Pool.GetList<ulong>();

            internal List<ulong> whitelist = Pool.GetList<ulong>();

            private Rigidbody rigidbody;

            internal Collider collider;

            internal Bounds bounds;

            private TriggerRadiation radiation;

            private TriggerComfort comfort;

            private TriggerTemperature temperature;

            private TriggerSafeZone safeZone;

            private GameObject radiationChild;

            private GameObject safeZoneChild;

            private bool isTogglingLights = false;

            private void Awake()
            {
                gameObject.layer = (int)Layer.Reserved1;
                gameObject.name = "ZoneManager";
            }

            private void OnDestroy()
            {
                EmptyZone();

                Pool.FreeList(ref players);
                Pool.FreeList(ref entities);
                Pool.FreeList(ref keepInList);
                Pool.FreeList(ref whitelist);
            }

            private void EmptyZone()
            {
                RemoveAllPlayers();

                keepInList.Clear();

                for (int i = players.Count - 1; i >= 0; i--)
                    Instance?.OnPlayerExitZone(players[i], this);

                for (int i = entities.Count - 1; i >= 0; i--)
                    Instance?.OnEntityExitZone(entities[i], this);
            }

            #region Zone Initialization
            public void InitializeZone(Definition definition)
            {
                this.definition = definition;

                transform.position = definition.Location;

                transform.rotation = Quaternion.Euler(definition.Rotation);

                if (definition.Enabled)
                {
                    RegisterPermission();

                    InitializeCollider();

                    InitializeAutoLights();

                    InitializeRadiation();

                    InitializeSafeZone();

                    InitializeComfort();

                    InitializeTemperature();

                    RemoveAllPlayers();
                    AddAllPlayers();
                }
                else
                {
                    InvokeHandler.CancelInvoke(this, CheckAlwaysLights);
                    InvokeHandler.CancelInvoke(this, CheckLights);

                    if (isLightsOn)
                        ServerMgr.Instance.StartCoroutine(ToggleLights(false));

                    EmptyZone();

                    if (collider != null)
                        DestroyImmediate(collider);

                    if (rigidbody != null)
                        DestroyImmediate(rigidbody);
                }
            }

            public void FindZoneParent()
            {
                if (string.IsNullOrEmpty(definition.ParentID))
                    return;

                Instance.zones.TryGetValue(definition.ParentID, out parent);
            }

            public void Reset()
            {
                InvokeHandler.CancelInvoke(this, CheckAlwaysLights);
                InvokeHandler.CancelInvoke(this, CheckLights);

                if (isLightsOn)
                    ServerMgr.Instance.StartCoroutine(ToggleLights(false));

                EmptyZone();

                InitializeZone(definition);
            }

            private void RegisterPermission()
            {
                if (!string.IsNullOrEmpty(definition.Permission) && !Instance.permission.PermissionExists(definition.Permission))
                    Instance.permission.RegisterPermission(definition.Permission, Instance);
            }

            private void InitializeCollider()
            {
                if (collider != null)
                    DestroyImmediate(collider);

                if (rigidbody != null)
                    DestroyImmediate(rigidbody);

                rigidbody = gameObject.AddComponent<Rigidbody>();
                rigidbody.useGravity = false;
                rigidbody.isKinematic = true;
                rigidbody.detectCollisions = true;
                rigidbody.collisionDetectionMode = CollisionDetectionMode.Discrete;

                SphereCollider sphereCollider = gameObject.GetComponent<SphereCollider>();
                BoxCollider boxCollider = gameObject.GetComponent<BoxCollider>();

                if (definition.Size != Vector3.zero)
                {
                    if (sphereCollider != null)
                        Destroy(sphereCollider);

                    if (boxCollider == null)
                    {
                        boxCollider = gameObject.AddComponent<BoxCollider>();
                        boxCollider.isTrigger = true;
                    }
                    boxCollider.size = definition.Size;
                    bounds = boxCollider.bounds;
                    collider = boxCollider;
                }
                else
                {
                    if (boxCollider != null)
                        Destroy(boxCollider);

                    if (sphereCollider == null)
                    {
                        sphereCollider = gameObject.AddComponent<SphereCollider>();
                        sphereCollider.isTrigger = true;
                    }
                    sphereCollider.radius = definition.Radius;
                    bounds = sphereCollider.bounds;
                    collider = sphereCollider;
                }
            }
            #endregion

            #region Triggers
            private void InitializeRadiation()
            {
                radiation = gameObject.GetComponent<TriggerRadiation>();
                if (definition.Radiation > 0)
                {
                    radiation = radiation ?? gameObject.AddComponent<TriggerRadiation>();
                    if (collider is BoxCollider)
                    {
                        radiationChild = gameObject.CreateChild();
                        SphereCollider sphereCollider = radiationChild.AddComponent<SphereCollider>();
                        sphereCollider.radius = Mathf.Max(bounds.size.x, bounds.size.y, bounds.size.z);
                    }
                    radiation.RadiationAmountOverride = definition.Radiation;
                    radiation.interestLayers = PLAYER_MASK;
                    radiation.enabled = this.enabled;
                }
                else
                {
                    if (radiation != null)
                        Destroy(radiation);

                    if (radiationChild != null)
                        Destroy(radiationChild);
                }
            }

            private void InitializeSafeZone()
            {
                safeZone = gameObject.GetComponent<TriggerSafeZone>();
                if (definition.SafeZone)
                {
                    safeZone = safeZone ?? gameObject.AddComponent<TriggerSafeZone>();
                    if (collider is BoxCollider)
                    {
                        safeZoneChild = gameObject.CreateChild();
                        SphereCollider sphereCollider = safeZoneChild.AddComponent<SphereCollider>();
                        sphereCollider.radius = Mathf.Max(bounds.size.x, bounds.size.y, bounds.size.z);
                    }
                    safeZone.interestLayers = PLAYER_MASK;
                    safeZone.enabled = this.enabled;
                }
                else
                {
                    if (safeZone != null)
                        Destroy(safeZone);

                    if (safeZoneChild != null)
                        Destroy(safeZoneChild);
                }
            }

            private void InitializeComfort()
            {
                comfort = gameObject.GetComponent<TriggerComfort>();
                if (definition.Comfort > 0)
                {
                    comfort = comfort ?? gameObject.AddComponent<TriggerComfort>();
                    comfort.baseComfort = definition.Comfort;
                    comfort.triggerSize = Mathf.Max(bounds.size.x, bounds.size.y, bounds.size.z);
                    comfort.interestLayers = PLAYER_MASK;
                    comfort.enabled = this.enabled;
                }
                else
                {
                    if (comfort != null)
                        Destroy(comfort);
                }
            }

            private void InitializeTemperature()
            {
                temperature = gameObject.GetComponent<TriggerTemperature>();
                if (definition.Temperature != 0)
                {
                    temperature = temperature ?? gameObject.AddComponent<TriggerTemperature>();
                    temperature.Temperature = definition.Temperature;
                    temperature.triggerSize = Mathf.Max(bounds.size.x, bounds.size.y, bounds.size.z);
                    temperature.interestLayers = PLAYER_MASK;
                    temperature.enabled = true;
                }
                else
                {
                    if (temperature != null)                    
                        Destroy(temperature);                    
                }
            }

            private void AddToTrigger(TriggerBase triggerBase, BasePlayer player)
            {
                if (triggerBase == null || player == null)
                    return;

                if (triggerBase.entityContents == null)
                    triggerBase.entityContents = new HashSet<BaseEntity>();

                triggerBase.entityContents.Add(player);
                player.EnterTrigger(triggerBase);

                if (triggerBase is TriggerSafeZone)
                {
                    if (player.IsItemHoldRestricted(player.inventory.containerBelt.FindItemByUID(player.svActiveItemID)))                    
                        player.UpdateActiveItem(0);

                    player.SetPlayerFlag(BasePlayer.PlayerFlags.SafeZone, true);
                }
            }

            private void RemoveFromTrigger(TriggerBase triggerBase, BasePlayer player)
            {
                if (triggerBase == null || player == null)
                    return;

                if (triggerBase.entityContents != null)
                    triggerBase.entityContents.Remove(player);

                player.LeaveTrigger(triggerBase);

                if (triggerBase is TriggerSafeZone)
                {
                    if (!player.InSafeZone())
                        player.SetPlayerFlag(BasePlayer.PlayerFlags.SafeZone, false);
                }
            }

            private void AddAllPlayers()
            {
                for (int i = 0; i < players.Count; i++)
                {
                    BasePlayer player = players[i];

                    AddToTrigger(radiation, player);
                    AddToTrigger(safeZone, player);
                    AddToTrigger(comfort, player);
                    AddToTrigger(temperature, player);
                }
            }

            private void RemoveAllPlayers()
            {
                for (int i = 0; i < players.Count; i++)
                {
                    BasePlayer player = players[i];

                    RemoveFromTrigger(radiation, player);
                    RemoveFromTrigger(safeZone, player);
                    RemoveFromTrigger(comfort, player);
                    RemoveFromTrigger(temperature, player);
                }
            }
            #endregion

            #region Autolights
            private bool isLightsOn = false;

            private void InitializeAutoLights()
            {
                if (HasFlag(ZoneFlags.AlwaysLights))
                {
                    isLightsOn = true;

                    InvokeHandler.CancelInvoke(this, CheckAlwaysLights);
                    InvokeHandler.InvokeRandomized(this, CheckAlwaysLights, 5f, 60f, 10f);
                }
                else if (HasFlag(ZoneFlags.AutoLights))
                {
                    InvokeHandler.CancelInvoke(this, CheckLights);
                    InvokeHandler.InvokeRandomized(this, CheckLights, 5f, 20f, 10f);
                }
            }

            private void CheckAlwaysLights()
            {
                ServerMgr.Instance.StartCoroutine(ToggleLights(true));
            }

            private void CheckLights()
            {
                float currentTime = TOD_Sky.Instance.Cycle.Hour;

                bool shouldBeActive = currentTime > Instance.configData.AutoLights.OnTime || currentTime < Instance.configData.AutoLights.OffTime;

                if (shouldBeActive != isLightsOn)
                {
                    isLightsOn = shouldBeActive;
                    ServerMgr.Instance.StartCoroutine(ToggleLights(isLightsOn));
                }
            }

            private IEnumerator ToggleLights(bool active)
            {
                while (isTogglingLights)
                    yield return null;

                isTogglingLights = true;

                bool requiresFuel = Instance.configData.AutoLights.RequiresFuel;

                for (int i = 0; i < entities.Count; i++)
                {
                    if (ToggleLight(entities[i], active, requiresFuel))
                        yield return CoroutineEx.waitForEndOfFrame;
                }

                isTogglingLights = false;
            }

            private bool ToggleLight(BaseEntity baseEntity, bool active, bool requiresFuel)
            {
                BaseOven baseOven = baseEntity as BaseOven;
                if (baseOven != null)
                {
                    if (active)
                    {
                        if (!baseOven.IsOn())
                        {
                            if ((requiresFuel && baseOven.FindBurnable() != null) || !requiresFuel)
                                baseOven.SetFlag(BaseEntity.Flags.On, true);
                        }
                    }
                    else
                    {
                        if (baseOven.IsOn())
                            baseOven.StopCooking();
                    }

                    return true;
                }

                SearchLight searchLight = baseEntity as SearchLight;
                if (searchLight != null)
                {
                    if (active)
                    {
                        if (!searchLight.IsOn())
                            searchLight.SetFlag(BaseEntity.Flags.On, true);
                    }
                    else
                    {
                        if (searchLight.IsOn())
                            searchLight.SetFlag(BaseEntity.Flags.On, false);
                    }

                    return true;
                }

                return false;
            }
            #endregion

            #region Entity Detection            
            private void OnTriggerEnter(Collider col)
            {
                if (!definition.Enabled)
                    return;

                BaseEntity baseEntity = col?.ToBaseEntity();
                if (!baseEntity?.IsValid() ?? false)
                    return;

                if (baseEntity is BasePlayer)
                {
                    Instance.OnPlayerEnterZone(baseEntity as BasePlayer, this);

                    if (parent != null)
                        Instance.UpdateZoneFlags(this);
                    return;
                }

                Instance.OnEntityEnterZone(baseEntity, this);
            }

            private void OnTriggerExit(Collider col)
            {
                if (!definition.Enabled)
                    return;

                BaseEntity baseEntity = col?.ToBaseEntity();
                if (!baseEntity?.IsValid() ?? false)
                    return;

                if (baseEntity is BasePlayer)
                {
                    Instance.OnPlayerExitZone(baseEntity as BasePlayer, this);

                    return;
                }

                Instance.OnEntityExitZone(baseEntity, this);
            }

            public void OnPlayerEnterZone(BasePlayer player)
            {
                if (!players.Contains(player))
                    players.Add(player);

                AddToTrigger(radiation, player);
                AddToTrigger(safeZone, player);
                AddToTrigger(comfort, player);
                AddToTrigger(temperature, player);
            }

            public void OnPlayerExitZone(BasePlayer player)
            {
                players.Remove(player);

                RemoveFromTrigger(radiation, player);
                RemoveFromTrigger(safeZone, player);
                RemoveFromTrigger(comfort, player);
                RemoveFromTrigger(temperature, player);
            }

            public void OnEntityEnterZone(BaseEntity baseEntity)
            {
                entities.Add(baseEntity);

                if (HasFlag(ZoneFlags.NoDecay))
                {
                    DecayEntity decayEntity = baseEntity.GetComponentInParent<DecayEntity>();
                    if (decayEntity != null)
                    {
                        decayEntity.decay = null;
                    }
                }

                if (HasFlag(ZoneFlags.NoStability))
                {
                    if (baseEntity is StabilityEntity)
                    {
                        (baseEntity as StabilityEntity).grounded = true;
                    }
                }

                if (HasFlag(ZoneFlags.NpcFreeze))
                {
                    if (baseEntity is BaseNpc)
                    {
                        baseEntity.CancelInvoke((baseEntity as BaseNpc).TickAi);
                    }
                }

                if (HasFlag(ZoneFlags.AlwaysLights) || (HasFlag(ZoneFlags.AutoLights) && isLightsOn))
                {
                    if (baseEntity is BaseOven || baseEntity is SearchLight)
                    {
                        ToggleLight(baseEntity, true, Instance.configData.AutoLights.RequiresFuel);
                    }
                }
            }

            public void OnEntityExitZone(BaseEntity baseEntity, bool resetDecay, bool isDead = false)
            {
                entities.Remove(baseEntity);

                if (isDead)
                    return;

                if (resetDecay)
                {
                    if (HasFlag(ZoneFlags.NoDecay))
                    {
                        DecayEntity decayEntity = baseEntity.GetComponentInParent<DecayEntity>();
                        if (decayEntity != null)
                        {
                            decayEntity.decay = PrefabAttribute.server.Find<Decay>(decayEntity.prefabID);
                        }
                    }
                }

                if (HasFlag(ZoneFlags.NpcFreeze))
                {
                    if (baseEntity is BaseNpc)
                    {
                        baseEntity.InvokeRandomized((baseEntity as BaseNpc).TickAi, 0.1f, 0.1f, 0.00500000035f);
                    }
                }

                if (HasFlag(ZoneFlags.AlwaysLights) || (HasFlag(ZoneFlags.AutoLights) && isLightsOn))
                {
                    if (baseEntity is BaseOven || baseEntity is SearchLight)
                    {
                        ToggleLight(baseEntity, false, false);
                    }
                }
            }
            #endregion

            #region Helpers
            public bool HasPermission(BasePlayer player) => string.IsNullOrEmpty(definition.Permission) ? true : Instance.permission.UserHasPermission(player.UserIDString, definition.Permission);

            public bool CanLeaveZone(BasePlayer player) => !keepInList.Contains(player.userID);

            public bool CanEnterZone(BasePlayer player) => HasPermission(player) || !CanLeaveZone(player) || whitelist.Contains(player.userID);

            private bool HasFlag(ZoneFlags flags) => (definition.Flags & ~disabledFlags & flags) == flags;
            #endregion

            #region Zone Definition
            public class Definition
            {
                public string Name { get; set; }
                public float Radius { get; set; }
                public float Radiation { get; set; }
                public float Comfort { get; set; }
                public float Temperature { get; set; }
                public bool SafeZone { get; set; }
                public Vector3 Location { get; set; }
                public Vector3 Size { get; set; }
                public Vector3 Rotation { get; set; }
                public string Id { get; set; }
                public string ParentID { get; set; }
                public string EnterMessage { get; set; }
                public string LeaveMessage { get; set; }
                public string Permission { get; set; }
                public string EjectSpawns { get; set; }
                public bool Enabled { get; set; } = true;
                public ZoneFlags Flags { get; set; }

                public Definition() { }

                public Definition(Vector3 position)
                {
                    Radius = 20f;
                    Location = position;
                }
            }
            #endregion
        }
        #endregion

        #region Entity Management
        private void OnPlayerEnterZone(BasePlayer player, Zone zone)
        {
            if (player == null)
                return;

            if (!zone.CanEnterZone(player))
            {
                EjectPlayer(player, zone);
                return;
            }

            if (HasFlag(zone, ZoneFlags.Eject))
            {
                if (!CanBypass(player, ZoneFlags.Eject) && !IsAdmin(player))
                {
                    EjectPlayer(player, zone);
                    return;
                }
            }

            if (HasFlag(zone, ZoneFlags.KeepVehiclesOut) && player.isMounted)
            {
                if (ReverseVelocity(player))
                {
                    SendMessage(player, Message("novehiclesenter", player.UserIDString));
                    return;
                }
            }

            if (player.IsSleeping() && !player.IsConnected)
            {
                if (HasFlag(zone, ZoneFlags.KillSleepers))
                {
                    if (!CanBypass(player, ZoneFlags.KillSleepers) && !IsAdmin(player))
                    {
                        player.Die();
                        return;
                    }
                }

                if (HasFlag(zone, ZoneFlags.EjectSleepers))
                {
                    if (!CanBypass(player, ZoneFlags.EjectSleepers) && !IsAdmin(player))
                    {
                        EjectPlayer(player, zone);
                        return;
                    }
                }
            }

            if (HasFlag(zone, ZoneFlags.Kill))
            {
                if (!CanBypass(player, ZoneFlags.Kill) && !IsAdmin(player))
                {
                    player.Die();
                    return;
                }
            }

            EntityZones entityZones;
            if (!zonedPlayers.TryGetValue(player.userID, out entityZones))
                zonedPlayers[player.userID] = entityZones = new EntityZones();

            if (!entityZones.EnterZone(zone))
                return;

            if (zone.parent != null)
                entityZones.UpdateFlags();
            else entityZones.AddFlags(zone.definition.Flags);

            zone.OnPlayerEnterZone(player);

            if (!string.IsNullOrEmpty(zone.definition.EnterMessage))
            {
                if (PopupNotifications != null && configData.Notifications.Popups)
                    PopupNotifications.Call("CreatePopupNotification", string.Format(zone.definition.EnterMessage, player.displayName), player);
                else SendMessage(player, zone.definition.EnterMessage, player.displayName);
            }

            Interface.CallHook("OnEnterZone", zone.definition.Id, player);
        }

        private void OnPlayerExitZone(BasePlayer player, Zone zone)
        {
            if (player == null)
                return;

            if (HasFlag(zone, ZoneFlags.KeepVehiclesIn) && player.isMounted)
            {
                if (ReverseVelocity(player))
                {
                    SendMessage(player, Message("novehiclesleave", player.UserIDString));
                    return;
                }
            }

            if (!zone.CanLeaveZone(player))
            {
                AttractPlayer(player, zone);
                return;
            }

            EntityZones entityZones;
            if (!zonedPlayers.TryGetValue(player.userID, out entityZones))
                return;

            entityZones.LeaveZone(zone);

            if (entityZones.ShouldRemove())

something else must also be blocking damage. i've confirmed this works fine

(14:51:41) | [TruePVE] 20415019
(14:51:41) | [TruePVE] Using RuleSet "pve"
(14:51:41) | [TruePVE] 20415019
(14:51:41) | [TruePVE] Using RuleSet "pve"
(14:51:41) | [TruePVE] 20415019
(14:51:41) | [TruePVE] Using RuleSet "pve"
(14:51:41) | [TruePVE] 20415019
(14:51:41) | [TruePVE] Using RuleSet "pve"​

using your exact config except 20415019 is my zone. yours is super small at only 20 radius so im not sure if that has anything to do with it or not. make sure both of you are inside of the zone. you will know because you both will get a message when you enter it. you should also run tpve.trace again.
======================
==  STARTING TRACE  ==
==  00:25:55.99188  ==
======================
 From: Scientist, scientist
 To: BasePlayer, player
  Checking exclusions between [45771961] and [45771961]
   Shared locations: 45771961
   No shared locations, or no matching exclusion mapping - no exclusions)
 No exclusion found - looking up RuleSet...
  Beginning RuleSet lookup for [45771961] and [45771961]
   Shared locations: 45771961
   Found 1 location names, with 1 mapped RuleSets
   Found RuleSet: pve
 Using RuleSet "pve"
 Initiator or target is HumanNPC, with HumanNPCDamage flag set; allow and return

======================
==  STARTING TRACE  ==
==  00:25:56.01687  ==
======================
 From: Scientist, scientist
 To: BasePlayer, player
  Checking exclusions between [45771961] and [45771961]
   Shared locations: 45771961
   No shared locations, or no matching exclusion mapping - no exclusions)
 No exclusion found - looking up RuleSet...
  Beginning RuleSet lookup for [45771961] and [45771961]
   Shared locations: 45771961
   Found 1 location names, with 1 mapped RuleSets
   Found RuleSet: pve
 Using RuleSet "pve"
 Initiator or target is HumanNPC, with HumanNPCDamage flag set; allow and return

======================
==  STARTING TRACE  ==
==  00:25:56.07983  ==
======================
 From: Scientist, scientist
 To: BasePlayer, player
  Checking exclusions between [45771961] and [45771961]
   Shared locations: 45771961
   No shared locations, or no matching exclusion mapping - no exclusions)
 No exclusion found - looking up RuleSet...
  Beginning RuleSet lookup for [45771961] and [45771961]
   Shared locations: 45771961
   Found 1 location names, with 1 mapped RuleSets
   Found RuleSet: pve
 Using RuleSet "pve"
 Initiator or target is HumanNPC, with HumanNPCDamage flag set; allow and return

======================
==  STARTING TRACE  ==
==  00:25:56.18302  ==
======================
 From: Scientist, scientist
 To: BasePlayer, player
  Checking exclusions between [45771961] and [45771961]
   Shared locations: 45771961
   No shared locations, or no matching exclusion mapping - no exclusions)
 No exclusion found - looking up RuleSet...
  Beginning RuleSet lookup for [45771961] and [45771961]
   Shared locations: 45771961
   Found 1 location names, with 1 mapped RuleSets
   Found RuleSet: pve
 Using RuleSet "pve"
 Initiator or target is HumanNPC, with HumanNPCDamage flag set; allow and return

======================
==  STARTING TRACE  ==
==  00:25:56.28197  ==
======================
 From: Scientist, scientist
 To: BasePlayer, player
  Checking exclusions between [45771961] and [45771961]
   Shared locations: 45771961
   No shared locations, or no matching exclusion mapping - no exclusions)
 No exclusion found - looking up RuleSet...
  Beginning RuleSet lookup for [45771961] and [45771961]
   Shared locations: 45771961
   Found 1 location names, with 1 mapped RuleSets
   Found RuleSet: pve
 Using RuleSet "pve"
 Initiator or target is HumanNPC, with HumanNPCDamage flag set; allow and return

======================
==  STARTING TRACE  ==
==  00:25:56.38591  ==
======================
 From: Scientist, scientist
 To: BasePlayer, player
  Checking exclusions between [45771961] and [45771961]
   Shared locations: 45771961
   No shared locations, or no matching exclusion mapping - no exclusions)
 No exclusion found - looking up RuleSet...
  Beginning RuleSet lookup for [45771961] and [45771961]
   Shared locations: 45771961
   Found 1 location names, with 1 mapped RuleSets
   Found RuleSet: pve
 Using RuleSet "pve"
 Initiator or target is HumanNPC, with HumanNPCDamage flag set; allow and return

Getting new messages this time

"Flags": "PvpGod, SleepGod"

pvpgod - true/false - Players will have PVP god mode

You have to remove that flag :p

The trace came back fine. It works as expected now.

Oh wow... I do not remember adding that. It now works! Thank you so much. One more thing. How can I make it so Player's can hurt themselves? 

Merged post

and also horses still seem to take damage even tho I set the flags ""players cannot hurt ridablehorses","

add the SelfDamage flag to the pve ruleset in truepve

Merged post

If players can hurt horses then its because of the AuthorizedDamage flag. Run a trace to confirm :p

Works thank you! This sounds a little nitpicky but... Traps don't deal damage to anyone, which is how I want it, but they also don't deal damage to whoever placed them. Is there a way around this?

Merged post

Also on top of this. "players cannot hurt mini", and everything related to players not being able to hurt vehicles do not work for me. I have set this up for all vehicles including horse and minicopter but I can still damage them

Merged post

======================
==  STARTING TRACE  ==
==  01:09:18.00566  ==
======================
 From: BasePlayer, player
 To: MiniCopter, minicopter.entity
  Checking exclusions between [45771961] and [45771961]
   Shared locations: 45771961
   No shared locations, or no matching exclusion mapping - no exclusions)
 No exclusion found - looking up RuleSet...
  Beginning RuleSet lookup for [45771961] and [45771961]
   Shared locations: 45771961
   Found 1 location names, with 1 mapped RuleSets
   Found RuleSet: pve
 Using RuleSet "pve"
 Initiator is player with authorization over non-player target; allow and return

======================
==  STARTING TRACE  ==
==  01:09:18.40967  ==
======================
 From: BasePlayer, player
 To: MiniCopter, minicopter.entity
  Checking exclusions between [45771961] and [45771961]
   Shared locations: 45771961
   No shared locations, or no matching exclusion mapping - no exclusions)
 No exclusion found - looking up RuleSet...
  Beginning RuleSet lookup for [45771961] and [45771961]
   Shared locations: 45771961
   Found 1 location names, with 1 mapped RuleSets
   Found RuleSet: pve
 Using RuleSet "pve"
 Initiator is player with authorization over non-player target; allow and return

======================
==  STARTING TRACE  ==
==  01:09:18.75737  ==
======================
 From: BasePlayer, player
 To: MiniCopter, minicopter.entity
  Checking exclusions between [45771961] and [45771961]
   Shared locations: 45771961
   No shared locations, or no matching exclusion mapping - no exclusions)
 No exclusion found - looking up RuleSet...
  Beginning RuleSet lookup for [45771961] and [45771961]
   Shared locations: 45771961
   Found 1 location names, with 1 mapped RuleSets
   Found RuleSet: pve
 Using RuleSet "pve"
 Initiator is player with authorization over non-player target; allow and return

======================
==  STARTING TRACE  ==
==  01:09:19.13314  ==
======================
 From: BasePlayer, player
 To: MiniCopter, minicopter.entity
  Checking exclusions between [45771961] and [45771961]
   Shared locations: 45771961
   No shared locations, or no matching exclusion mapping - no exclusions)
 No exclusion found - looking up RuleSet...
  Beginning RuleSet lookup for [45771961] and [45771961]
   Shared locations: 45771961
   Found 1 location names, with 1 mapped RuleSets
   Found RuleSet: pve
 Using RuleSet "pve"
 Initiator is player with authorization over non-player target; allow and return

======================
==  STARTING TRACE  ==
==  01:09:19.38300  ==
======================
 From: BasePlayer, player
 To: MiniCopter, minicopter.entity
  Checking exclusions between [45771961] and [45771961]
   Shared locations: 45771961
   No shared locations, or no matching exclusion mapping - no exclusions)
 No exclusion found - looking up RuleSet...
  Beginning RuleSet lookup for [45771961] and [45771961]
   Shared locations: 45771961
   Found 1 location names, with 1 mapped RuleSets
   Found RuleSet: pve
 Using RuleSet "pve"
 Initiator is player with authorization over non-player target; allow and return

nope, no way around it

its because of the AuthorizedDamage flag. Run a trace to confirm :p

Here's the Landmine log

======================
==  STARTING TRACE  ==
==  01:14:56.89343  ==
======================
 From: Landmine, landmine
 To: BasePlayer, player
  Checking exclusions between [45771961] and [45771961]
   Shared locations: 45771961
   No shared locations, or no matching exclusion mapping - no exclusions)
 No exclusion found - looking up RuleSet...
  Beginning RuleSet lookup for [45771961] and [45771961]
   Shared locations: 45771961
   Found 1 location names, with 1 mapped RuleSets
   Found RuleSet: pve
 Using RuleSet "pve"
 No match in pre-checks; evaluating RuleSet rules...
  Initator EntityGroup matches: traps
  Target EntityGroup matches: players
   Evaluating Rules...
    Checking direct initiator->target rules...
     Evaluating "traps->players"...
      Match found; allow damage? False​


Merged post

I just added the "CupboardOwnership" flag and this fixed my issue with vehicles. Now they don't take damage within TC range. Is there a way to do this regardless or not? For some reason Horses don't take damage whatsoever

now Im confused 

I'm honestly confusing myself :D So basically the "player cannot hurt ridablehorses" works and I cannot hurt horses no matter where they are in the PVE zone. However for some reason I can still hurt minicopters as an example. I managed to fix this by adding the "Cupboard Ownership" flag, but obviously I'd prefer if players couldn't damage Minicopters regardless if it's by a TC or not.

Merged post

Here's my config to possibly make you understand it better.

{
  "Config Version": "2.0.2",
  "Default RuleSet": "default",
  "Configuration Options": {
    "handleDamage": true,
    "useZones": true
  },
  "Mappings": {
    "default": "default",
    "45771961": "pve"
  },
  "Schedule": {
    "enabled": false,
    "useRealtime": false,
    "broadcast": false,
    "entries": []
  },
  "RuleSets": [
    {
      "name": "default",
      "enabled": true,
      "defaultAllowDamage": true,
      "flags": "HumanNPCDamage",
      "rules": [
        "anything can hurt anything"
      ]
    },
    {
      "name": "pve",
      "enabled": true,
      "defaultAllowDamage": false,
      "flags": "HumanNPCDamage, LockedBoxesImmortal, LockedDoorsImmortal, AuthorizedDamage, SelfDamage, CupboardOwnership",
      "rules": [
        "anything can hurt dispensers",
        "anything can hurt players",
        "players cannot hurt players",
        "anything can hurt traps",
        "traps cannot hurt players",
        "players cannot hurt traps",
        "players cannot hurt barricades",
        "players cannot hurt mini",
        "players cannot hurt cars",
        "players cannot hurt scrapheli",
		"players cannot hurt ridablehorses",
        "barricades can hurt players",
        "highwalls can hurt players",
        "heli can hurt everything",
        "anything can hurt heli",
        "anything can hurt mini",
        "anything can hurt scrapheli",
        "anything can hurt cars",
        "anything can hurt ch47",
		"anything can hurt ridablehorses",
        "fire can hurt everything",
        "anything can hurt resources",
        "npcs can hurt players"
      ]
    }
  ],
  "Allow Killing Sleepers": false,
  "Entity Groups": [
    {
      "name": "barricades",
      "members": "Barricade, icewall, GraveYardFence",
      "exclusions": "barricade.concrete, barricade.sandbags, barricade.metal, barricade.stone, barricade.wood, barricade.woodwire"
    },
    {
      "name": "dispensers",
      "members": "BaseCorpse, HelicopterDebris, NPCPlayerCorpse, HorseCorpse, PlayerCorpse",
      "exclusions": ""
    },
    {
      "name": "fire",
      "members": "FireBall, FlameExplosive, rocket_heli_napalm, napalm, oilfireball2",
      "exclusions": "FlameThrower, BaseOven"
    },
    {
      "name": "guards",
      "members": "bandit_guard, scientistpeacekeeper, sentry.scientist.static",
      "exclusions": ""
    },
    {
      "name": "heli",
      "members": "BaseHelicopter",
      "exclusions": ""
    },
    {
      "name": "highwalls",
      "members": "SimpleBuildingBlock, wall.external.high.ice, gates.external.high.stone, gates.external.high.wood",
      "exclusions": ""
    },
    {
      "name": "ridablehorses",
      "members": "RidableHorse",
      "exclusions": ""
    },
    {
      "name": "cars",
      "members": "BasicCar, ModularCar, BaseModularVehicle, BaseVehicleModule, VehicleModuleEngine, VehicleModuleSeating, VehicleModuleStorage, VehicleModuleTaxi, ModularCarSeat",
      "exclusions": ""
    },
    {
      "name": "mini",
      "members": "MiniCopter",
      "exclusions": ""
    },
    {
      "name": "scrapheli",
      "members": "ScrapTransportHelicopter",
      "exclusions": ""
    },
    {
      "name": "ch47",
      "members": "ch47.entity",
      "exclusions": ""
    },
    {
      "name": "npcs",
      "members": "ch47scientists.entity, BradleyAPC, HTNAnimal, HTNPlayer, HumanNPC, NPCMurderer, NPCPlayer, Scientist, ScientistNPC, Zombie",
      "exclusions": ""
    },
    {
      "name": "players",
      "members": "BasePlayer",
      "exclusions": ""
    },
    {
      "name": "resources",
      "members": "ResourceEntity, TreeEntity, OreResourceEntity, LootContainer",
      "exclusions": "hobobarrel.deployed"
    },
    {
      "name": "samsites",
      "members": "sam_site_turret_deployed",
      "exclusions": "sam_static"
    },
    {
      "name": "traps",
      "members": "AutoTurret, BearTrap, FlameTurret, Landmine, GunTrap, ReactiveTarget, TeslaCoil, spikes.floor",
      "exclusions": ""
    }
  ]
}​

Also could you please check if I did the Fire Entity Group right? Basically I don't want Flamethrowers or Minicopter Crash Fire to damage buildings/structures.

well that's just how AuthorizedDamage works. best I can suggest is to pair it with AuthorizedDamageRequiresOwnership so only the owner can hurt it.

if you are referring to the minicopter taking collision damage, then that damage is not dealt by the player, but by itself. so you would need to use mini cannot hurt mini rule

your fire group will not work for that specific case, because FireBall is in the members group. almost all fire inherits FireBall, meaning you'd have to remove it and add each one individually using their shortname found with /tpve_prod or by running a trace. it'll take time to find them all.

I tried to find them all, might be missing one or two... I am using shortnames here instead of types... types are too broad for what you want to use this for

[assets/bundled/prefabs/fireball.prefab, 3369311876]
[assets/bundled/prefabs/fireball_small.prefab, 2086405370]
[assets/bundled/prefabs/fireball_small_arrow.prefab, 1081379866]
[assets/bundled/prefabs/fireball_small_shotgun.prefab, 1837652231]
[assets/bundled/prefabs/oilfireballsmall.prefab, 3550347674]
[assets/prefabs/npc/m2bradley/oilfireball2.prefab, 3761185980]
[assets/bundled/prefabs/static/campfire_static.prefab, 1339281147]
[assets/prefabs/npc/flame turret/flameturret_fireball.prefab, 2781905939]
[assets/bundled/prefabs/fireball.prefab, 3369311876]
[assets/bundled/prefabs/fireball_small.prefab, 2086405370]
[assets/bundled/prefabs/fireball_small_arrow.prefab, 1081379866]
[assets/bundled/prefabs/fireball_small_shotgun.prefab, 1837652231]
[assets/bundled/prefabs/oilfireballsmall.prefab, 3550347674]
[assets/prefabs/npc/m2bradley/oilfireball2.prefab, 3761185980]
[assets/bundled/prefabs/static/campfire_static.prefab, 1339281147]
[assets/prefabs/npc/flame turret/flameturret_fireball.prefab, 2781905939]
[assets/prefabs/weapons/flamethrower/flamethrower_fireball.prefab, 844008300]
[assets/bundled/prefabs/napalm.prefab, 184893264]
[assets/prefabs/npc/patrol helicopter/rocket_heli_napalm.prefab, 200672762]
[assets/prefabs/ammo/rocket/rocket_fire.prefab, 901927673]
[assets/prefabs/ammo/rifle/riflebullet_fire.prefab, 2828814118]

these are all prefabs. so you would want to put their shortname in either members or exclusions. for example, the last one's shortname would be riflebullet_fire​