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

FREE DynamicPVP : 4.2.13 4.2.13

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
 //Requires: ZoneManager
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Facepunch;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Oxide.Plugins {
    [Info("Dynamic PVP", "CatMeat/Arainrr", "4.2.13", ResourceId = 2728)]
    [Description("Creates temporary PvP zones on certain actions/events")]
    public class DynamicPVP : RustPlugin {
#region Fields
        [PluginReference]
        private readonly Plugin ZoneManager, BotReSpawn;
        private const string PermissionAdmin = "dynamicpvp.admin";
        private const string PrefabSphere = "assets/prefabs/visualization/sphere.prefab";
        private const string ZoneName = "DynamicPVP";
        private static object _true, _false;
        private readonly Dictionary<string, Timer> _eventTimers = new Dictionary<string, Timer>();
        private readonly Dictionary<ulong, LeftZone> _pvpDelays = new Dictionary<ulong, LeftZone>();
        private readonly Dictionary<string, string> _activeDynamicZones = new Dictionary<string, string>();
        //ID -> EventName
        private bool _dataChanged;
        private Vector3 _oilRigPosition;
        private Vector3 _largeOilRigPosition;
        private Coroutine _createEventsCoroutine;
        public static DynamicPVP Instance {
            get;
            private set;
        }
        private class LeftZone : Pool.IPooled {
            public string zoneId;
            public string eventName;
            public Timer zoneTimer;
            public void EnterPool() {
                zoneId = null;
                eventName = null;
                zoneTimer?.Destroy();
                zoneTimer = null;
            }
            public void LeavePool() {
            }
        }
        [Flags]
        [JsonConverter(typeof(StringEnumConverter))]
        private enum PVPDelayFlags {
            None = 0, ZonePlayersCanDamageDelayedPlayers = 1, DelayedPlayersCanDamageZonePlayers = 1 << 1, DelayedPlayersCanDamageDelayedPlayers = 1 << 2
        }
        private enum GeneralEventType {
            Bradley, Helicopter, SupplyDrop, SupplySignal, CargoShip, HackableCrate, ExcavatorIgnition
        }
#endregion Fields
#region Oxide Hooks
        private void Init() {
            Instance = this;
            LoadData();
            _true = true;
            _false = false;
            permission.RegisterPermission(PermissionAdmin, this);
            AddCovalenceCommand(configData.Chat.Command, nameof(CmdDynamicPVP));
            Unsubscribe(nameof(OnEntitySpawned));
            Unsubscribe(nameof(OnCargoPlaneSignaled));
            Unsubscribe(nameof(OnCrateHack));
            Unsubscribe(nameof(OnDieselEngineToggled));
            Unsubscribe(nameof(OnEntityDeath));
            Unsubscribe(nameof(OnLootEntity));
            Unsubscribe(nameof(OnCrateHackEnd));
            Unsubscribe(nameof(OnSupplyDropLanded));
            Unsubscribe(nameof(OnEntityKill));
            Unsubscribe(nameof(OnPlayerCommand));
            Unsubscribe(nameof(OnServerCommand));
            Unsubscribe(nameof(CanEntityTakeDamage));
            Unsubscribe(nameof(OnEnterZone));
            Unsubscribe(nameof(OnExitZone));
            if (configData.Global.LogToFile) {
                _debugStringBuilder = new StringBuilder();
            }
        }
        private void OnServerInitialized() {
            //Pool.FillBuffer<LeftZone>();
            DeleteOldDynamicZones();
            _createEventsCoroutine = ServerMgr.Instance.StartCoroutine(CreateMonumentEvents());
            if (configData.GeneralEvents.ExcavatorIgnition.Enabled) {
                Subscribe(nameof(OnDieselEngineToggled));
            }
            if (configData.GeneralEvents.PatrolHelicopter.Enabled || configData.GeneralEvents.BradleyApc.Enabled) {
                Subscribe(nameof(OnEntityDeath));
            }
            if (configData.GeneralEvents.SupplySignal.Enabled || configData.GeneralEvents.TimedSupply.Enabled) {
                Subscribe(nameof(OnCargoPlaneSignaled));
            }
            if (configData.GeneralEvents.HackableCrate.Enabled && configData.GeneralEvents.HackableCrate.TimerStartWhenUnlocked) {
                Subscribe(nameof(OnCrateHackEnd));
            }
            if (configData.GeneralEvents.TimedSupply.Enabled && configData.GeneralEvents.TimedSupply.TimerStartWhenLooted || configData.GeneralEvents.SupplySignal.Enabled && configData.GeneralEvents.SupplySignal.TimerStartWhenLooted || configData.GeneralEvents.HackableCrate.Enabled && configData.GeneralEvents.HackableCrate.TimerStartWhenLooted) {
                Subscribe(nameof(OnLootEntity));
            }
            if (configData.GeneralEvents.HackableCrate.Enabled && !configData.GeneralEvents.HackableCrate.StartWhenSpawned) {
                Subscribe(nameof(OnCrateHack));
            }
            if (configData.GeneralEvents.TimedSupply.Enabled && !configData.GeneralEvents.TimedSupply.StartWhenSpawned || configData.GeneralEvents.SupplySignal.Enabled && !configData.GeneralEvents.SupplySignal.StartWhenSpawned) {
                Subscribe(nameof(OnSupplyDropLanded));
            }
            if (configData.GeneralEvents.TimedSupply.Enabled && configData.GeneralEvents.TimedSupply.StartWhenSpawned || configData.GeneralEvents.SupplySignal.Enabled && configData.GeneralEvents.SupplySignal.StartWhenSpawned || configData.GeneralEvents.HackableCrate.Enabled && configData.GeneralEvents.HackableCrate.StartWhenSpawned) {
                Subscribe(nameof(OnEntitySpawned));
            }
            if (configData.GeneralEvents.TimedSupply.Enabled && configData.GeneralEvents.TimedSupply.StopWhenKilled || configData.GeneralEvents.SupplySignal.Enabled && configData.GeneralEvents.SupplySignal.StopWhenKilled || configData.GeneralEvents.HackableCrate.Enabled && configData.GeneralEvents.HackableCrate.StopWhenKilled) {
                Subscribe(nameof(OnEntityKill));
            }
            if (configData.GeneralEvents.CargoShip.Enabled) {
                Subscribe(nameof(OnEntityKill));
                Subscribe(nameof(OnEntitySpawned));
                foreach (var serverEntity in BaseNetworkable.serverEntities) {
                    var cargoShip = serverEntity as CargoShip;
                    if (cargoShip == null) {
                        continue;
                    }
                    OnEntitySpawned(cargoShip);
                }
            }
        }
        private void Unload() {
            if (_createEventsCoroutine != null) {
                ServerMgr.Instance.StopCoroutine(_createEventsCoroutine);
            }
            if (_activeDynamicZones.Count > 0) {
                PrintDebug($"Deleting {_activeDynamicZones.Count} active zones.", true);
                foreach (var entry in _activeDynamicZones.ToArray()) {
                    DeleteDynamicZone(entry.Key);
                }
            }
            var leftZones = _pvpDelays.Values.ToArray();
            for (var i = leftZones.Length - 1; i >= 0; i--) {
                var value = leftZones[i];
                Pool.Free(ref value);
            }
            var spheres = _zoneSpheres.Values.ToArray();
            for (var i = spheres.Length - 1; i >= 0; i--) {
                var sphereEntities = spheres[i];
                foreach (var sphereEntity in sphereEntities) {
                    if (sphereEntity != null && !sphereEntity.IsDestroyed) {
                        sphereEntity.KillMessage();
                    }
                }
                Pool.FreeList(ref sphereEntities);
            }
            SaveData();
            SaveDebug();
            Pool.directory.Remove(typeof(LeftZone));
            _true = _false = null;
            Instance = null;
        }
        private void OnServerSave() {
            timer.Once(Random.Range(0f, 60f), () => {
                SaveDebug();
                if (_dataChanged) {
                    SaveData();
                    _dataChanged = false;
                }
            }
            );
        }
        private void OnPlayerRespawned(BasePlayer player) {
            if (player == null || !player.userID.IsSteamId()) {
                return;
            }
            TryRemovePVPDelay(player.userID, player.displayName);
        }
#endregion Oxide Hooks
#region Methods
        private void TryRemoveEventTimer(string zoneId) {
            Timer value;
            if (_eventTimers.TryGetValue(zoneId, out value)) {
                value?.Destroy();
                _eventTimers.Remove(zoneId);
            }
        }
        private LeftZone GetOrAddPVPDelay(BasePlayer player, string zoneId, string eventName) {
            PrintDebug($"Adding {player.displayName} to pvp delay.");
            var added = false;
            LeftZone leftZone;
            if (_pvpDelays.TryGetValue(player.userID, out leftZone)) {
                leftZone.zoneTimer?.Destroy();
            }
            else {
                added = true;
                leftZone = Pool.Get<LeftZone>();
                _pvpDelays.Add(player.userID, leftZone);
            }
            leftZone.zoneId = zoneId;
            leftZone.eventName = eventName;
            if (added) {
                CheckHooks(true);
            }
            return leftZone;
        }
        private void TryRemovePVPDelay(ulong playerId, string playerName) {
            PrintDebug($"Removing {playerName} from pvp delay.");
            LeftZone leftZone;
            if (_pvpDelays.TryGetValue(playerId, out leftZone)) {
                _pvpDelays.Remove(playerId);
                Interface.CallHook("OnPlayerRemovedFromPVPDelay", playerId, leftZone.zoneId);
                Pool.Free(ref leftZone);
                CheckHooks(true);
            }
        }
        private bool CheckEntityOwner(BaseEntity baseEntity) {
            if (configData.Global.CheckEntityOwner && baseEntity.OwnerID.IsSteamId()) {
                PrintDebug($"{baseEntity} is owned by the player({baseEntity.OwnerID}).Skipping event creation.");
                return false;
            }
            return true;
        }
        private bool CanCreateDynamicPVP(string eventName, BaseEntity entity) {
            if (Interface.CallHook("OnCreateDynamicPVP", eventName, entity) != null) {
                PrintDebug($"There are other plugins that prevent {eventName} events from being created.", true);
                return false;
            }
            return true;
        }
        private void CheckHooks(bool pvpDelay = false) {
            if (pvpDelay) {
                if (_pvpDelays.Count > 0) {
                    Subscribe(nameof(CanEntityTakeDamage));
                }
                else {
                    Unsubscribe(nameof(CanEntityTakeDamage));
                }
            }
            else {
                if (_activeDynamicZones.Count > 0) {
                    Subscribe(nameof(OnEnterZone));
                    Subscribe(nameof(OnExitZone));
                }
                else {
                    Unsubscribe(nameof(OnEnterZone));
                    Unsubscribe(nameof(OnExitZone));
                }
            }
            var hasCommands = false;
            foreach (var eventName in _activeDynamicZones.Values) {
                var baseEvent = GetBaseEvent(eventName);
                if (baseEvent != null && baseEvent.CommandList.Count > 0) {
                    hasCommands = true;
                    break;
                }
            }
            if (!hasCommands) {
                foreach (var leftZone in _pvpDelays.Values) {
                    var baseEvent = GetBaseEvent(leftZone.eventName);
                    if (baseEvent != null && baseEvent.CommandList.Count > 0 && baseEvent.CommandWorksForPVPDelay) {
                        hasCommands = true;
                        break;
                    }
                }
            }
            if (hasCommands) {
                Subscribe(nameof(OnPlayerCommand));
                Subscribe(nameof(OnServerCommand));
            }
            else {
                Unsubscribe(nameof(OnPlayerCommand));
                Unsubscribe(nameof(OnServerCommand));
            }
        }
        private BaseEvent GetBaseEvent(string eventName) {
            if (string.IsNullOrEmpty(eventName)) {
                throw new ArgumentNullException(nameof(eventName));
            }
            var externalEvent = Interface.CallHook("OnGetBaseEvent", eventName) as BaseEvent;
            if (externalEvent != null) {
                return externalEvent;
            }
            if (Enum.IsDefined(typeof(GeneralEventType), eventName)) {
                GeneralEventType generalEventType;
                if (Enum.TryParse(eventName, true, out generalEventType)) {
                    switch (generalEventType) {
                        case GeneralEventType.Bradley : return configData.GeneralEvents.BradleyApc;
                        case GeneralEventType.HackableCrate : return configData.GeneralEvents.HackableCrate;
                        case GeneralEventType.Helicopter : return configData.GeneralEvents.PatrolHelicopter;
                        case GeneralEventType.SupplyDrop : return configData.GeneralEvents.TimedSupply;
                        case GeneralEventType.SupplySignal : return configData.GeneralEvents.SupplySignal;
                        case GeneralEventType.ExcavatorIgnition : return configData.GeneralEvents.ExcavatorIgnition;
                        case GeneralEventType.CargoShip : return configData.GeneralEvents.CargoShip;
                        default : PrintDebug($"ERROR: Unknown GeneralEventType: {generalEventType} | {eventName}.", error : true);
                        break;
                    }
                }
            }
            AutoEvent autoEvent;
            if (storedData.autoEvents.TryGetValue(eventName, out autoEvent)) {
                return autoEvent;
            }
            TimedEvent timedEvent;
            if (storedData.timedEvents.TryGetValue(eventName, out timedEvent)) {
                return timedEvent;
            }
            MonumentEvent monumentEvent;
            if (configData.MonumentEvents.TryGetValue(eventName, out monumentEvent)) {
                return monumentEvent;
            }
            PrintDebug($"ERROR: Failed to get base event settings for {eventName}.", error : true);
            return null;
        }
#endregion Methods
#region Events
#region General Event
#region ExcavatorIgnition Event
        private void OnDieselEngineToggled(DieselEngine dieselEngine) {
            if (dieselEngine == null || dieselEngine.net == null) {
                return;
            }
            var zoneId = dieselEngine.net.ID.ToString();
            if (dieselEngine.IsOn()) {
                DeleteDynamicZone(zoneId);
                HandleGeneralEvent(GeneralEventType.ExcavatorIgnition, dieselEngine, true);
            }
            else {
                HandleDeleteDynamicZone(zoneId);
            }
        }
#endregion ExcavatorIgnition Event
#region HackableLockedCrate Event
        private void OnEntitySpawned(HackableLockedCrate hackableLockedCrate) {
            if (hackableLockedCrate == null || hackableLockedCrate.net == null) {
                return;
            }
            if (!configData.GeneralEvents.HackableCrate.Enabled || !configData.GeneralEvents.HackableCrate.StartWhenSpawned) {
                return;
            }
            PrintDebug("Trying to create the event when the hackable locked crate is spawned.");
            NextTick(() => LockedCrateEvent(hackableLockedCrate));
        }
        private void OnCrateHack(HackableLockedCrate hackableLockedCrate) {
            if (hackableLockedCrate == null || hackableLockedCrate.net == null) {
                return;
            }
            PrintDebug("Trying to create the event when the hackable locked crate is starting hack.");
            NextTick(() => LockedCrateEvent(hackableLockedCrate));
        }
        private void OnCrateHackEnd(HackableLockedCrate hackableLockedCrate) {
            if (hackableLockedCrate == null || hackableLockedCrate.net == null) {
                return;
            }
            HandleDeleteDynamicZone(hackableLockedCrate.net.ID.ToString(), configData.GeneralEvents.HackableCrate.Duration, GeneralEventType.HackableCrate.ToString());
        }
        private void OnLootEntity(BasePlayer player, HackableLockedCrate hackableLockedCrate) {
            if (hackableLockedCrate == null || hackableLockedCrate.net == null) {
                return;
            }
            if (!configData.GeneralEvents.HackableCrate.Enabled || !configData.GeneralEvents.HackableCrate.TimerStartWhenLooted) {
                return;
            }
            HandleDeleteDynamicZone(hackableLockedCrate.net.ID.ToString(), configData.GeneralEvents.HackableCrate.Duration, GeneralEventType.HackableCrate.ToString());
        }
        private void OnEntityKill(HackableLockedCrate hackableLockedCrate) {
            if (hackableLockedCrate == null || hackableLockedCrate.net == null) {
                return;
            }
            if (!configData.GeneralEvents.HackableCrate.Enabled || !configData.GeneralEvents.HackableCrate.StopWhenKilled) {
                return;
            }
            var zoneId = hackableLockedCrate.net.ID.ToString();
            //When the timer starts, don't stop the event immediately
            if (!_eventTimers.ContainsKey(zoneId)) {
                HandleDeleteDynamicZone(hackableLockedCrate.net.ID.ToString());
            }
        }
        private void LockedCrateEvent(HackableLockedCrate hackableLockedCrate) {
            if (!CheckEntityOwner(hackableLockedCrate)) {
                return;
            }
            if (configData.GeneralEvents.HackableCrate.ExcludeOilRig && IsOnTheOilRig(hackableLockedCrate)) {
                PrintDebug("The hackable locked crate is on the oil rig.Skipping event creation.");
                return;
            }
            if (configData.GeneralEvents.HackableCrate.ExcludeCargoShip && IsOnTheCargoShip(hackableLockedCrate)) {
                PrintDebug("The hackable locked crate is on the cargo ship.Skipping event creation.");
                return;
            }
            HandleGeneralEvent(GeneralEventType.HackableCrate, hackableLockedCrate, true);
        }
        private bool IsOnTheCargoShip(HackableLockedCrate hackableLockedCrate) {
            return hackableLockedCrate.GetComponentInParent<CargoShip>() != null;
        }
        private bool IsOnTheOilRig(HackableLockedCrate hackableLockedCrate) {
            if (_oilRigPosition != Vector3.zero && Vector3Ex.Distance2D(hackableLockedCrate.transform.position, _oilRigPosition) < 50f) {
                return true;
            }
            if (_largeOilRigPosition != Vector3.zero && Vector3Ex.Distance2D(hackableLockedCrate.transform.position, _largeOilRigPosition) < 50f) {
                return true;
            }
            return false;
        }
#endregion HackableLockedCrate Event
#region BaseHelicopter And BradleyAPC Event
        private void OnEntityDeath(BaseHelicopter baseHelicopter, HitInfo info) {
            if (baseHelicopter == null || baseHelicopter.net == null) {
                return;
            }
            PatrolHelicopterEvent(baseHelicopter);
        }
        private void OnEntityDeath(BradleyAPC bradleyApc, HitInfo info) {
            if (bradleyApc == null || bradleyApc.net == null) {
                return;
            }
            BradleyApcEvent(bradleyApc);
        }
        private void PatrolHelicopterEvent(BaseHelicopter baseHelicopter) {
            if (!configData.GeneralEvents.PatrolHelicopter.Enabled) {
                return;
            }
            PrintDebug("Trying to create the event when the helicopter is dead.");
            if (!CheckEntityOwner(baseHelicopter)) {
                return;
            }
            HandleGeneralEvent(GeneralEventType.Helicopter, baseHelicopter, false);
        }
        private void BradleyApcEvent(BradleyAPC bradleyAPC) {
            if (!configData.GeneralEvents.BradleyApc.Enabled) {
                return;
            }
            PrintDebug("Trying to create the event when the bradley apc is dead.");
            if (!CheckEntityOwner(bradleyAPC)) {
                return;
            }
            HandleGeneralEvent(GeneralEventType.Bradley, bradleyAPC, false);
        }
#endregion BaseHelicopter And BradleyAPC Event
#region SupplyDrop And SupplySignal Event
        private readonly Dictionary<Vector3, Timer> activeSupplySignals = new Dictionary<Vector3, Timer>();
        private void OnCargoPlaneSignaled(CargoPlane cargoPlane, SupplySignal supplySignal) {
            NextTick(() => {
                if (supplySignal == null || cargoPlane == null) {
                    return;
                }
                var dropPosition = cargoPlane.dropPosition;
                if (activeSupplySignals.ContainsKey(dropPosition)) {
                    return;
                }
                activeSupplySignals.Add(dropPosition, timer.Once(900f, () => activeSupplySignals.Remove(dropPosition)));
                PrintDebug($"A supply signal is thrown at {dropPosition}");
            }
            );
        }
        private void OnEntitySpawned(SupplyDrop supplyDrop) {
            NextTick(() => OnSupplyDropEvent(supplyDrop, false));
        }
        private void OnSupplyDropLanded(SupplyDrop supplyDrop) {
            if (supplyDrop == null || supplyDrop.net == null) {
                return;
            }
            if (_activeDynamicZones.ContainsKey(supplyDrop.net.ID.ToString())) {
                return;
            }
            NextTick(() => OnSupplyDropEvent(supplyDrop, true));
        }
        private void OnLootEntity(BasePlayer player, SupplyDrop supplyDrop) {
            if (supplyDrop == null || supplyDrop.net == null) {
                return;
            }
            var zoneId = supplyDrop.net.ID.ToString();
            string eventName;
            if (_activeDynamicZones.TryGetValue(zoneId, out eventName)) {
                switch (eventName) {
                    case nameof(GeneralEventType.SupplySignal) : if (!configData.GeneralEvents.SupplySignal.Enabled || !configData.GeneralEvents.SupplySignal.TimerStartWhenLooted) {
                        return;
                    }
                    HandleDeleteDynamicZone(zoneId, configData.GeneralEvents.SupplySignal.Duration, eventName);
                    break;
                    case nameof(GeneralEventType.SupplyDrop) : if (!configData.GeneralEvents.TimedSupply.Enabled || !configData.GeneralEvents.TimedSupply.TimerStartWhenLooted) {
                        return;
                    }
                    HandleDeleteDynamicZone(zoneId, configData.GeneralEvents.TimedSupply.Duration, eventName);
                    break;
                    default : return;
                }
            }
        }
        private void OnEntityKill(SupplyDrop supplyDrop) {
            if (supplyDrop == null || supplyDrop.net == null) {
                return;
            }
            var zoneId = supplyDrop.net.ID.ToString();
            string eventName;
            if (_activeDynamicZones.TryGetValue(zoneId, out eventName)) {
                switch (eventName) {
                    case nameof(GeneralEventType.SupplySignal) : if (!configData.GeneralEvents.SupplySignal.Enabled || !configData.GeneralEvents.SupplySignal.StopWhenKilled) {
                        return;
                    }
                    break;
                    case nameof(GeneralEventType.SupplyDrop) : if (!configData.GeneralEvents.TimedSupply.Enabled || !configData.GeneralEvents.TimedSupply.StopWhenKilled) {
                        return;
                    }
                    break;
                    default : return;
                }
                //When the timer starts, don't stop the event immediately
                if (!_eventTimers.ContainsKey(zoneId)) {
                    HandleDeleteDynamicZone(zoneId);
                }
            }
        }
        private void OnSupplyDropEvent(SupplyDrop supplyDrop, bool isLanded) {
            if (supplyDrop == null || supplyDrop.net == null) {
                return;
            }
            PrintDebug($"Trying to create the event when the supply drop is {(isLanded ? "landed" : "spawned")} at {supplyDrop.transform.position}.");
            if (!CheckEntityOwner(supplyDrop)) {
                return;
            }
            Action action = null;
            var isFromSupplySignal = IsProbablySupplySignal(supplyDrop.transform.position, ref action);
            PrintDebug($"Supply drop is from supply signal: {isFromSupplySignal}");
            if (isFromSupplySignal) {
                if (!configData.GeneralEvents.SupplySignal.Enabled) {
                    PrintDebug("Event for supply signals disabled.Skipping event creation.");
                    return;
                }
                if (isLanded ? configData.GeneralEvents.SupplySignal.StartWhenSpawned : !configData.GeneralEvents.SupplySignal.StartWhenSpawned) {
                    PrintDebug($"{(isLanded ? "Landed" : "Spawned")} for supply signals disabled.");
                    return;
                }
                action?.Invoke();
                HandleGeneralEvent(GeneralEventType.SupplySignal, supplyDrop, true);
            }
            else {
                if (!configData.GeneralEvents.TimedSupply.Enabled) {
                    PrintDebug("Event for timed supply disabled.Skipping event creation.");
                    return;
                }
                if (isLanded ? configData.GeneralEvents.TimedSupply.StartWhenSpawned : !configData.GeneralEvents.TimedSupply.StartWhenSpawned) {
                    PrintDebug($"{(isLanded ? "Landed" : "Spawned")} for timed supply disabled.");
                    return;
                }
                HandleGeneralEvent(GeneralEventType.SupplyDrop, supplyDrop, true);
            }
        }
        private bool IsProbablySupplySignal(Vector3 position, ref Action action) {
            PrintDebug($"Checking {activeSupplySignals.Count} active supply signals");
            if (activeSupplySignals.Count > 0) {
                foreach (var entry in activeSupplySignals) {
                    var distance = Vector3Ex.Distance2D(entry.Key, position);
                    PrintDebug($"Found a supply signal at {entry.Key} located {distance}m away.");
                    if (distance <= configData.Global.CompareRadius) {
                        action = () => {
                            entry.Value?.Destroy();
                            activeSupplySignals.Remove(entry.Key);
                            PrintDebug($"Removing Supply signal from active list.Active supply signals remaining: {activeSupplySignals.Count}");
                        }
                        ;
                        PrintDebug("Found matching a supply signal.");
                        return true;
                    }
                }
                PrintDebug("No matches found, probably from a timed event cargo plane");
                return false;
            }
            PrintDebug("No active signals, must be from a timed event cargo plane");
            return false;
        }
#endregion SupplyDrop And SupplySignal Event
#region CargoShip Event
        private void OnEntitySpawned(CargoShip cargoShip) {
            if (cargoShip == null || cargoShip.net == null) {
                return;
            }
            if (!configData.GeneralEvents.CargoShip.Enabled) {
                return;
            }
            PrintDebug("Trying to create the event when the cargo ship is spawned.");
            if (!CheckEntityOwner(cargoShip)) {
                return;
            }
            var eventName = GeneralEventType.CargoShip.ToString();
            if (!CanCreateDynamicPVP(eventName, cargoShip)) {
                return;
            }
            NextTick(() => HandleParentedEntityEvent(eventName, cargoShip));
        }
        private void OnEntityKill(CargoShip cargoShip) {
            if (cargoShip == null || cargoShip.net == null) {
                return;
            }
            if (!configData.GeneralEvents.CargoShip.Enabled) {
                return;
            }
            HandleDeleteDynamicZone(cargoShip.net.ID.ToString());
        }
#endregion CargoShip Event
#endregion General Event
#region Monument Event
        private IEnumerator CreateMonumentEvents() {
            var changed = false;
            var createdEvents = new List<string>();
            foreach (var landmarkInfo in TerrainMeta.Path.Landmarks) {
                if (!landmarkInfo.shouldDisplayOnMap) {
                    continue;
                }
                var monumentName = landmarkInfo.displayPhrase.english.Replace("\n", "");
                if (string.IsNullOrEmpty(monumentName)) {
                    continue;
                }
                switch (landmarkInfo.name) {
                    case "OilrigAI" : _oilRigPosition = landmarkInfo.transform.position;
                    break;
                    case "OilrigAI2" : _largeOilRigPosition = landmarkInfo.transform.position;
                    break;
                    case "assets/bundled/prefabs/autospawn/monument/harbor/harbor_1.prefab" : monumentName += " A";
                    break;
                    case "assets/bundled/prefabs/autospawn/monument/harbor/harbor_2.prefab" : monumentName += " B";
                    break;
                    //case "assets/bundled/prefabs/autospawn/monument/harbor/fishing_village_b.prefab": monumentName += " A"; break;
                    //case "assets/bundled/prefabs/autospawn/monument/harbor/fishing_village_c.prefab": monumentName += " B"; break;
                }
                MonumentEvent monumentEvent;
                if (!configData.MonumentEvents.TryGetValue(monumentName, out monumentEvent)) {
                    changed = true;
                    monumentEvent = new MonumentEvent();
                    configData.MonumentEvents.Add(monumentName, monumentEvent);
                    Puts($"A new monument {monumentName} was found and added to the config.");
                }
                if (monumentEvent.Enabled) {
                    if (HandleMonumentEvent(monumentName, landmarkInfo.transform, monumentEvent)) {
                        createdEvents.Add(monumentName);
                    }
                    yield return CoroutineEx.waitForSeconds(0.5f);
                }
            }
            if (changed) {
                SaveConfig();
            }
            if (createdEvents.Count > 0) {
                PrintDebug($"{createdEvents.Count}({string.Join(", ", createdEvents)}) monument events were successfully created.", true);
            }
            createdEvents.Clear();
            foreach (var entry in storedData.autoEvents) {
                if (entry.Value.AutoStart) {
                    if (CreateDynamicZone(entry.Key, entry.Value.Position, entry.Value.ZoneId)) {
                        createdEvents.Add(entry.Key);
                    }
                    yield return CoroutineEx.waitForSeconds(0.5f);
                }
            }
            if (createdEvents.Count > 0) {
                PrintDebug($"{createdEvents.Count}({string.Join(", ", createdEvents)}) auto events were successfully created.", true);
            }
            _createEventsCoroutine = null;
        }
#endregion Monument Event
#region Chat/Console Command Handler
        private object OnPlayerCommand(BasePlayer player, string command, string[] args) {
            return CheckCommand(player, command, true);
        }
        private object OnServerCommand(ConsoleSystem.Arg arg) {
            return CheckCommand(arg?.Player(), arg?.cmd?.FullName, false);
        }
        private object CheckCommand(BasePlayer player, string command, bool isChat) {
            if (player == null || string.IsNullOrEmpty(command)) {
                return null;
            }
            command = command.ToLower().TrimStart('/');
            if (string.IsNullOrEmpty(command)) {
                return null;
            }
            LeftZone leftZone;
            if (_pvpDelays.TryGetValue(player.userID, out leftZone)) {
                var baseEvent = GetBaseEvent(leftZone.eventName);
                if (baseEvent != null && baseEvent.CommandWorksForPVPDelay) {
                    if (IsBlockedCommand(baseEvent, command, isChat)) {
                        return _false;
                    }
                }
            }
            var result = GetPlayerZoneIds(player);
            if (result == null || result.Length == 0 || result.Length == 1 && string.IsNullOrEmpty(result[0])) {
                return null;
            }
            foreach (var zoneId in result) {
                string eventName;
                if (_activeDynamicZones.TryGetValue(zoneId, out eventName)) {
                    PrintDebug($"Checking command: {command} , zoneId: {zoneId}");
                    var baseEvent = GetBaseEvent(eventName);
                    if (baseEvent != null) {
                        if (IsBlockedCommand(baseEvent, command, isChat)) {
                            return _false;
                        }
                    }
                }
            }
            return null;
        }
        private bool IsBlockedCommand(BaseEvent baseEvent, string command, bool isChat) {
            if (baseEvent != null && baseEvent.CommandList.Count > 0) {
                var commandExist = baseEvent.CommandList.Any(entry => isChat ? entry.StartsWith("/") && entry.Substring(1).Equals(command) : !entry.StartsWith("/") && command.Contains(entry));
                if (baseEvent.UseBlacklistCommands) {
                    if (commandExist) {
                        PrintDebug($"Use blacklist, Blocked command: {command}", true);
                        return true;
                    }
                }
                else {
                    if (!commandExist) {
                        PrintDebug($"Use whitelist, Blocked command: {command}", true);
                        return true;
                    }
                }
            }
            return false;
        }
#endregion Chat/Console Command Handler
#endregion Events
#region DynamicZone Handler
        private void HandleParentedEntityEvent(string eventName, BaseEntity parentEntity, bool delay = true) {
            if (parentEntity == null || parentEntity.net == null) {
                return;
            }
            var baseEvent = GetBaseEvent(eventName);
            if (baseEvent == null) {
                return;
            }
            if (delay && baseEvent.EventStartDelay > 0f) {
                timer.Once(baseEvent.EventStartDelay, () => HandleParentedEntityEvent(eventName, parentEntity, false));
                return;
            }
            PrintDebug($"Trying to create parented entity event {eventName} on entity({parentEntity}).");
            var zoneId = parentEntity.net.ID.ToString();
            var parentZone = baseEvent.GetDynamicZone() as IParentZone;
            if (CreateDynamicZone(eventName, parentEntity.transform.position, zoneId, delay : false)) {
                timer.Once(0.25f, () => {
                    var zone = GetZoneById(zoneId);
                    PrintDebug($"Gets the zone({zoneId} | {zone}) created by the {eventName} event.", true);
                    if (parentEntity != null && zone != null) {
                        var zoneTransform = zone.transform;
                        zoneTransform.SetParent(parentEntity.transform);
                        zoneTransform.rotation = parentEntity.transform.rotation;
                        zoneTransform.position = parentZone != null ? parentEntity.transform.TransformPoint(parentZone.Center) : parentEntity.transform.position;
                        PrintDebug($"The zone({zoneId} | {eventName}) was parented to entity({parentEntity}).", true);
                    }
                    else {
                        PrintDebug($"ERROR: The zone({zoneId} | {zone} | {parentEntity}) created by the {eventName} event is empty.", error : true);
                        DeleteDynamicZone(zoneId);
                    }
                }
                );
            }
        }
        private bool HandleMonumentEvent(string eventName, Transform transform, MonumentEvent monumentEvent) {
            var position = monumentEvent.TransformPosition != Vector3.zero ? transform.TransformPoint(monumentEvent.TransformPosition) : transform.position;
            return CreateDynamicZone(eventName, position, monumentEvent.ZoneId, monumentEvent.GetDynamicZone().ZoneSettings(transform));
        }
        private bool HandleGeneralEvent(GeneralEventType generalEventType, BaseEntity baseEntity, bool useEntityId) {
            var eventName = generalEventType.ToString();
            if (useEntityId && _activeDynamicZones.ContainsKey(baseEntity.net.ID.ToString())) {
                PrintDebug($"The event({eventName} | {baseEntity.net.ID}) created by entity({baseEntity}) already exists");
                return false;
            }
            if (!CanCreateDynamicPVP(eventName, baseEntity)) {
                return false;
            }
            var baseEvent = GetBaseEvent(eventName);
            if (baseEvent == null) {
                return false;
            }
            var position = baseEntity.transform.position;
            position.y = TerrainMeta.HeightMap.GetHeight(position);
            return CreateDynamicZone(eventName, position, useEntityId ? baseEntity.net.ID.ToString() : null, baseEvent.GetDynamicZone().ZoneSettings(baseEntity.transform));
        }
        private bool CreateDynamicZone(string eventName, Vector3 position, string zoneId = "", string[] zoneSettings = null, bool delay = true) {
            if (position == Vector3.zero) {
                PrintDebug($"ERROR: Invalid location, zone({eventName}) creation failed.Skipping event creation.", error : true);
                return false;
            }
            var baseEvent = GetBaseEvent(eventName);
            if (baseEvent == null) {
                return false;
            }
            if (delay && baseEvent.EventStartDelay > 0f) {
                timer.Once(baseEvent.EventStartDelay, () => CreateDynamicZone(eventName, position, zoneId, zoneSettings, false));
                return false;
            }
            float duration = -1;
            var timedEvent = baseEvent as ITimedEvent;
            if (timedEvent != null) {
                var timedDisable = baseEvent as ITimedDisable;
                if (timedDisable == null || !timedDisable.IsTimedDisabled()) {
                    duration = timedEvent.Duration;
                }
            }
            if (string.IsNullOrEmpty(zoneId)) {
                zoneId = DateTime.Now.ToString("HHmmssffff");
            }
            var dynamicZone = baseEvent.GetDynamicZone();
            zoneSettings = zoneSettings ?? dynamicZone.ZoneSettings();
            PrintDebug($"Trying create zone: {eventName}({zoneId} | {position}) {(dynamicZone is ISphereZone ? $"(Radius : {
                (dynamicZone as ISphereZone).Radius
            }
            m)" : $"(Size : {
                (dynamicZone as ICubeZone)?.Size
            }
            )")} {(dynamicZone is IParentZone ? $"(Center : {
                (dynamicZone as IParentZone).Center
            }
            ) " : null)}(Duration: {duration}s).");
            var zoneAdded = CreateZone(zoneId, zoneSettings, position);
            if (zoneAdded) {
                if (!_activeDynamicZones.ContainsKey(zoneId)) {
                    _activeDynamicZones.Add(zoneId, eventName);
                    CheckHooks();
                }
                var stringBuilder = Pool.Get<StringBuilder>();
                stringBuilder.Clear();
                var domeEvent = baseEvent as IDomeEvent;
                var sphereZone = dynamicZone as ISphereZone;
                if (DomeCreateAllowed(domeEvent, sphereZone)) {
                    var domeAdded = CreateDome(zoneId, position, sphereZone.Radius, domeEvent.DomesDarkness);
                    if (!domeAdded) {
                        PrintDebug($"ERROR: Dome NOT added for zone({zoneId}).", error : true);
                    }
                    else {
                        stringBuilder.Append("Dome,");
                    }
                }
                var botEvent = baseEvent as IBotEvent;
                if (BotReSpawnAllowed(botEvent)) {
                    var botsSpawned = SpawnBots(position, botEvent.BotProfileName, zoneId);
                    if (!botsSpawned) {
                        PrintDebug($"ERROR: Bot NOT spawned for zone({zoneId}).", error : true);
                    }
                    else {
                        stringBuilder.Append("Bots,");
                    }
                }
                var mappingAdded = TryCreateMapping(zoneId, baseEvent.Mapping);
                if (!mappingAdded) {
                    PrintDebug($"ERROR: Mapping Not added for zone({zoneId}).", error : true);
                }
                else {
                    stringBuilder.Append("Mapping,");
                }
                PrintDebug($"Created zone({zoneId} | {eventName}) ({stringBuilder.ToString().TrimEnd(',')}).", true);
                HandleDeleteDynamicZone(zoneId, duration, eventName);
                stringBuilder.Clear();
                Pool.Free(ref stringBuilder);
                return true;
            }
            PrintDebug($"ERROR: Create zone({eventName}) failed.", error : true);
            return false;
        }
        private void HandleDeleteDynamicZone(string zoneId, float duration, string eventName) {
            if (duration > 0f) {
                TryRemoveEventTimer(zoneId);
                PrintDebug($"The zone({zoneId} | {eventName}) will be deleted after {duration} seconds.", true);
                _eventTimers.Add(zoneId, timer.Once(duration, () => HandleDeleteDynamicZone(zoneId)));
            }
        }
        private void HandleDeleteDynamicZone(string zoneId) {
            string eventName;
            if (string.IsNullOrEmpty(zoneId) || !_activeDynamicZones.TryGetValue(zoneId, out eventName)) {
                PrintDebug($"ERROR: Invalid zoneID: {zoneId}.", error : true);
                return;
            }
            if (Interface.CallHook("OnDeleteDynamicPVP", zoneId, eventName) != null) {
                return;
            }
            var baseEvent = GetBaseEvent(eventName);
            if (baseEvent == null) {
                return;
            }
            if (baseEvent.EventStopDelay > 0f) {
                TryRemoveEventTimer(zoneId);
                if (baseEvent.GetDynamicZone() is IParentZone) {
                    var zone = GetZoneById(zoneId);
                    if (zone != null) {
                        zone.transform.SetParent(null, true);
                    }
                }
                _eventTimers.Add(zoneId, timer.Once(baseEvent.EventStopDelay, () => DeleteDynamicZone(zoneId)));
            }
            else {
                DeleteDynamicZone(zoneId);
            }
        }
        private bool DeleteDynamicZone(string zoneId) {
            string eventName;
            if (string.IsNullOrEmpty(zoneId) || !_activeDynamicZones.TryGetValue(zoneId, out eventName)) {
                PrintDebug($"ERROR: Invalid zoneID: {zoneId}.", error : true);
                return false;
            }
            TryRemoveEventTimer(zoneId);
            var baseEvent = GetBaseEvent(eventName);
            if (baseEvent == null) {
                return false;
            }
            var stringBuilder = Pool.Get<StringBuilder>();
            stringBuilder.Clear();
            var dynamicZone = baseEvent.GetDynamicZone();
            if (DomeCreateAllowed(baseEvent as IDomeEvent, dynamicZone as ISphereZone)) {
                var domeRemoved = RemoveDome(zoneId);
                if (!domeRemoved) {
                    PrintDebug($"ERROR: Dome NOT removed for zone({zoneId} | {eventName}).", error : true);
                }
                else {
                    stringBuilder.Append("Dome,");
                }
            }
            if (BotReSpawnAllowed(baseEvent as IBotEvent)) {
                var botsRemoved = KillBots(zoneId);
                if (!botsRemoved) {
                    PrintDebug($"ERROR: Bot NOT killed for zone({zoneId} | {eventName}).", error : true);
                }
                else {
                    stringBuilder.Append("Bots,");
                }
            }
            var mappingRemoved = TryRemoveMapping(zoneId);
            if (!mappingRemoved) {
                PrintDebug($"ERROR: Mapping NOT removed for zone({zoneId} | {eventName}).", error : true);
            }
            else {
                stringBuilder.Append("Mapping,");
            }
            var players = GetPlayersInZone(zoneId);
            var zoneRemoved = RemoveZone(zoneId, eventName);
            if (zoneRemoved) {
                // Release zone players immediately
                PrintDebug($"Release zone players : {string.Join(", ", players.Select(x => x.displayName))}");
                foreach (var player in players) {
                    OnExitZone(zoneId, player);
                }
                if (_activeDynamicZones.Remove(zoneId)) {
                    CheckHooks();
                }
                PrintDebug($"Deleted zone({zoneId} | {eventName}) ({stringBuilder.ToString().TrimEnd(',')}).", true);
            }
            else {
                PrintDebug($"ERROR: Delete zone({zoneId} | {eventName} | {stringBuilder.ToString().TrimEnd(',')}) failed.", error : true);
            }
            stringBuilder.Clear();
            Pool.Free(ref stringBuilder);
            return zoneRemoved;
        }
        private void DeleteOldDynamicZones() {
            var zoneIds = GetZoneIds();
            if (zoneIds == null || zoneIds.Length <= 0) {
                return;
            }
            int attempts = 0, successes = 0;
            foreach (var zoneId in zoneIds) {
                var zoneName = GetZoneName(zoneId);
                if (zoneName == ZoneName) {
                    attempts++;
                    var zoneRemoved = RemoveZone(zoneId);
                    if (zoneRemoved) {
                        successes++;
                    }
                    TryRemoveMapping(zoneId);
                }
            }
    
// ... [Code preview truncated due to length. Full source in attached file] ...

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