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

FREE GuardedCrate : 2.0.5 2.0.5

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6

/*
 * Copyright (c) 2023 Bazz3l
 * 
 * Guarded Crate cannot be copied, edited and/or (re)distributed without the express permission of Bazz3l.* 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.* 
 */
using System.Collections.Generic;
using System.Globalization;
using System.Collections;
using System.Text;
using System.Linq;
using System;
using Oxide.Core.Plugins;
using Oxide.Core;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using GuardedCrateEx;
using UnityEngine;
using Rust;
namespace Oxide.Plugins {
    [Info("Guarded Crate", "Bazz3l", "2.0.5")]
    [Description("Spawn high value loot guarded by scientists at random or specified locations.")]
    internal class GuardedCrate : RustPlugin {
        [PluginReference]
        private Plugin NpcSpawn, Clans, ZoneManager, HackableLock, GUIAnnouncements;
#region Fields
        private const string PERM_USE = "guardedcrate.use";
        private const TerrainTopology.Enum BLOCKED_TOPOLOGY = TerrainTopology.Enum.Cliffside | TerrainTopology.Enum.Cliff | TerrainTopology.Enum.Lake | TerrainTopology.Enum.Ocean | TerrainTopology.Enum.Monument | TerrainTopology.Enum.Building | TerrainTopology.Enum.Offshore | TerrainTopology.Enum.River | TerrainTopology.Enum.Swamp;
        private const string MARKER_PREFAB = "assets/prefabs/tools/map/genericradiusmarker.prefab";
        private const string CRATE_PREFAB = "assets/prefabs/deployable/chinooklockedcrate/codelockedhackablecrate.prefab";
        private const string PLANE_PREFAB = "assets/prefabs/npc/cargo plane/cargo_plane.prefab";
        private ConfigData _configData;
        private StoredData _storedData;
        private static GuardedCrate _instance;
#endregion
#region Config
        protected override void LoadDefaultConfig() {
            _configData = ConfigData.DefaultConfig();
            PrintWarning("Loaded default config.");
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                _configData = Config.ReadObject<ConfigData>();
                if (_configData == null) throw new JsonException();
                bool hasChanged = false;
                if (_configData.CommandName == null) {
                    PrintWarning("Updated config.");
                    LoadDefaultConfig();
                    hasChanged = true;
                }
                if (_configData.MessageSettings == null) {
                    _configData.MessageSettings = new MessageSettings {
                        EnableToast = false, EnableChat = true, EnableChatPrefix = true, ChatIcon = 76561199542824781, EnableGuiAnnouncements = false, GuiAnnouncementsBgColor = "Purple", GuiAnnouncementsTextColor = "White"
                    }
                    ;
                    hasChanged = true;
                }
                if (_configData.ZoneManagerSettings == null) {
                    _configData.ZoneManagerSettings = new ZoneMangerSettings {
                        EnabledIgnoredZones = false, IgnoredZones = new List<string>()
                    }
                    ;
                    hasChanged = true;
                }
                if (hasChanged) SaveConfig();
            }
            catch(Exception e) {
                PrintWarning(e.Message);
                LoadDefaultConfig();
            }
        }
        protected override void SaveConfig() => Config.WriteObject(_configData, true);
        private class ConfigData {
            [JsonProperty("command name")]
            public string CommandName;
            [JsonProperty("enable auto spawning events")]
            public bool EnableAutoStart;
            [JsonProperty("auto start event after x duration")]
            public float AutoStartDuration;
            [JsonProperty("message notification settings")]
            public MessageSettings MessageSettings;
            [JsonProperty("zone manager settings")]
            public ZoneMangerSettings ZoneManagerSettings;
            public static ConfigData DefaultConfig() {
                return new ConfigData {
                    CommandName = "gcrate", EnableAutoStart = true, AutoStartDuration = 3600, MessageSettings = new MessageSettings {
                        EnableToast = false, EnableChat = true, EnableChatPrefix = true, ChatIcon = 76561199542824781, EnableGuiAnnouncements = false, GuiAnnouncementsBgColor = "Purple", GuiAnnouncementsTextColor = "White"
                    }
                    , ZoneManagerSettings = new ZoneMangerSettings {
                        EnabledIgnoredZones = false, IgnoredZones = new List<string>()
                    }
                }
                ;
            }
        }
        private class MessageSettings {
            [JsonProperty("enable toast message")]
            public bool EnableToast;
            [JsonProperty("enable chat message")]
            public bool EnableChat;
            [JsonProperty("enable chat prefix")]
            public bool EnableChatPrefix;
            [JsonProperty("custom chat message icon (steam64)")]
            public ulong ChatIcon;
            [JsonProperty("enable gui announcements plugin from umod.org")]
            public bool EnableGuiAnnouncements;
            [JsonProperty("gui announcements text color")]
            public string GuiAnnouncementsTextColor;
            [JsonProperty("gui announcements background color")]
            public string GuiAnnouncementsBgColor;
        }
        private class ZoneMangerSettings {
            [JsonProperty("enable ignored zones")]
            public bool EnabledIgnoredZones;
            [JsonProperty("ignore these zone ids, leave empty to exclude all zones")]
            public List<string> IgnoredZones;
        }
#endregion
#region Storage
        private void LoadDefaultData() {
            _storedData = new StoredData();
            _storedData.CrateEventEntries = new List<EventEntry> {
                new() {
                    EventName = "Easy", EventDuration = 1800.0f, EnableAutoHack = true, HackSeconds = 60f, EnableLockToPlayer = true, EnableClanTag = true, EnableMarker = true, MapMarkerColor1 = "#32A844", MapMarkerColor2 = "#000000", MapMarkerOpacity = 0.6f, MapMarkerRadius = 0.7f, EnableLootTable = false, LootMinAmount = 6, LootMaxAmount = 10, LootTable = new List<ItemEntry>(), EnableEliminateGuards = true, GuardAmount = 8, GuardConfig = new GuardConfig {
                        Name = "Easy Crate", WearItems = new List<GuardConfig.WearEntry> {
                            new() {
                                ShortName = "hazmatsuit_scientist_peacekeeper", SkinID = 0UL
                            }
                        }
                        , BeltItems = new List<GuardConfig.BeltEntry> {
                            new() {
                                ShortName = "smg.mp5", Amount = 1, SkinID = 0UL, Mods = new List<string>()
                            }
                            , new() {
                                ShortName = "syringe.medical", Amount = 10, SkinID = 0UL, Mods = new List<string>()
                            }
                            ,
                        }
                        , Kit = "", Health = 200.0f, RoamRange = 5.0f, ChaseRange = 40.0f, SenseRange = 150.0f, AttackRangeMultiplier = 8.0f, CheckVisionCone = false, VisionCone = 180.0f, DamageScale = 1.0f, TurretDamageScale = 0.25f, AimConeScale = 0.25f, DisableRadio = false, CanRunAwayWater = true, CanSleep = false, SleepDistance = 100f, Speed = 8.5f, AboveOrUnderGround = false, Stationary = false, MemoryDuration = 30.0f
                    }
                }
                , new() {
                    EventName = "Medium", EventDuration = 1800.0f, EnableAutoHack = true, HackSeconds = 120.0f, EnableLockToPlayer = true, EnableClanTag = true, EnableMarker = true, MapMarkerColor1 = "#EDDF45", MapMarkerColor2 = "#000000", MapMarkerOpacity = 0.6f, MapMarkerRadius = 0.7f, EnableLootTable = false, LootMinAmount = 6, LootMaxAmount = 10, LootTable = new List<ItemEntry>(), EnableEliminateGuards = true, GuardAmount = 10, GuardConfig = new GuardConfig {
                        Name = "Medium Guard", WearItems = new List<GuardConfig.WearEntry> {
                            new() {
                                ShortName = "hazmatsuit_scientist_peacekeeper", SkinID = 0UL
                            }
                        }
                        , BeltItems = new List<GuardConfig.BeltEntry> {
                            new() {
                                ShortName = "smg.mp5", Amount = 1, SkinID = 0UL, Mods = new List<string>()
                            }
                            , new() {
                                ShortName = "syringe.medical", Amount = 10, SkinID = 0UL, Mods = new List<string>()
                            }
                            ,
                        }
                        , Kit = "", Health = 250.0f, RoamRange = 5.0f, ChaseRange = 40.0f, SenseRange = 150.0f, AttackRangeMultiplier = 8.0f, CheckVisionCone = false, VisionCone = 180.0f, DamageScale = 1.0f, TurretDamageScale = 0.25f, AimConeScale = 0.25f, DisableRadio = false, CanRunAwayWater = true, CanSleep = false, SleepDistance = 100f, Speed = 8.5f, AboveOrUnderGround = false, Stationary = false, MemoryDuration = 30.0f
                    }
                }
                , new() {
                    EventName = "Hard", EventDuration = 1800.0f, EnableAutoHack = true, HackSeconds = 180.0f, EnableLockToPlayer = true, EnableClanTag = true, EnableMarker = true, MapMarkerColor1 = "#3060D9", MapMarkerColor2 = "#000000", MapMarkerOpacity = 0.6f, MapMarkerRadius = 0.7f, EnableLootTable = false, LootMinAmount = 6, LootMaxAmount = 10, LootTable = new List<ItemEntry>(), EnableEliminateGuards = true, GuardAmount = 12, GuardConfig = new GuardConfig {
                        Name = "Hard Guard", WearItems = new List<GuardConfig.WearEntry> {
                            new() {
                                ShortName = "hazmatsuit_scientist_peacekeeper", SkinID = 0UL
                            }
                        }
                        , BeltItems = new List<GuardConfig.BeltEntry> {
                            new() {
                                ShortName = "rifle.ak", Amount = 1, SkinID = 0UL, Mods = new List<string>()
                            }
                            , new() {
                                ShortName = "syringe.medical", Amount = 10, SkinID = 0UL, Mods = new List<string>()
                            }
                            ,
                        }
                        , Kit = "", Health = 300.0f, RoamRange = 5.0f, ChaseRange = 40.0f, SenseRange = 150.0f, AttackRangeMultiplier = 8.0f, CheckVisionCone = false, VisionCone = 180.0f, DamageScale = 1.0f, TurretDamageScale = 0.25f, AimConeScale = 0.15f, DisableRadio = false, CanRunAwayWater = true, CanSleep = false, SleepDistance = 100f, Speed = 8.5f, AboveOrUnderGround = false, Stationary = false, MemoryDuration = 30.0f
                    }
                }
            }
            ;
            SaveData();
        }
        private void LoadData() {
            try {
                _storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(Name);
                if (_storedData == null || !_storedData.IsValid) throw new Exception();
            }
            catch {
                PrintWarning("Loaded default data.");
                LoadDefaultData();
            }
        }
        private void SaveData() {
            if (_storedData == null || !_storedData.IsValid) return;
            Interface.Oxide.DataFileSystem.WriteObject(Name, _storedData);
        }
        private class StoredData {
            public List<EventEntry> CrateEventEntries = new();
            [JsonIgnore]
            private string[] _eventNames;
            [JsonIgnore]
            public string[] EventNames {
                get {
                    return _eventNames ??= CrateEventEntries.Select(x => x.EventName).ToArray();
                }
            }
            [JsonIgnore]
            public bool IsValid => CrateEventEntries != null && CrateEventEntries.Count > 0;
            public EventEntry FindEventByName(string eventName) {
                return CrateEventEntries.Find(x => x.EventName.Equals(eventName, StringComparison.OrdinalIgnoreCase));
            }
        }
        private class EventEntry {
            [JsonProperty("event display name)")]
            public string EventName;
            [JsonProperty("event duration")]
            public float EventDuration;
            [JsonProperty("enable lock to player when completing the event")]
            public bool EnableLockToPlayer;
            [JsonProperty("enable clan tag")]
            public bool EnableClanTag;
            [JsonProperty("enable auto hacking of crate when an event is finished")]
            public bool EnableAutoHack;
            [JsonProperty("hackable locked crate")]
            public float HackSeconds;
            [JsonProperty("enable marker")]
            public bool EnableMarker;
            [JsonProperty("marker color 1")]
            public string MapMarkerColor1;
            [JsonProperty("marker color 2")]
            public string MapMarkerColor2;
            [JsonProperty("marker radius")]
            public float MapMarkerRadius;
            [JsonProperty("marker opacity")]
            public float MapMarkerOpacity;
            [JsonProperty("enable loot table")]
            public bool EnableLootTable;
            [JsonProperty("min loot items")]
            public int LootMinAmount;
            [JsonProperty("max loot items")]
            public int LootMaxAmount;
            [JsonProperty("enable eliminate all guards before looting")]
            public bool EnableEliminateGuards;
            [JsonProperty("guard spawn amount")]
            public int GuardAmount;
            [JsonProperty("guard spawn config")]
            public GuardConfig GuardConfig;
            [JsonProperty("create loot items")]
            public List<ItemEntry> LootTable;
        }
        private class ItemEntry {
            public string DisplayName;
            public string Shortname;
            public ulong SkinID = 0UL;
            public int MinAmount;
            public int MaxAmount;
            public static List<ItemEntry> SaveItems(ItemContainer container) {
                List<ItemEntry> items = new List<ItemEntry>();
                foreach (Item item in container.itemList) {
                    items.Add(new ItemEntry {
                        DisplayName = item.name, Shortname = item.info.shortname, SkinID = item.skin, MinAmount = item.amount, MaxAmount = item.amount,
                    }
                    );
                }
                return items;
            }
            public Item CreateItem() {
                Item item = ItemManager.CreateByName(Shortname, UnityEngine.Random.Range(MinAmount, MaxAmount), SkinID);
                item.name = DisplayName;
                item.MarkDirty();
                return item;
            }
        }
        private class GuardConfig {
            public string Name;
            public List<WearEntry> WearItems;
            public List<BeltEntry> BeltItems;
            public string Kit;
            public float Health;
            public float RoamRange;
            public float ChaseRange;
            public float SenseRange;
            public float AttackRangeMultiplier;
            public bool CheckVisionCone;
            public float VisionCone;
            public float DamageScale;
            public float TurretDamageScale;
            public float AimConeScale;
            public bool HostileTargetsOnly;
            public bool DisableRadio;
            public bool CanRunAwayWater;
            public bool CanSleep;
            public float SleepDistance;
            public float Speed;
            public bool AboveOrUnderGround;
            public bool Stationary;
            public float MemoryDuration;
            [JsonIgnore]
            public JObject Parsed;
            public class BeltEntry {
                public string ShortName;
                public ulong SkinID;
                public int Amount;
                public string Ammo;
                public List<string> Mods;
                public static List<BeltEntry> SaveItems(ItemContainer container) {
                    List<BeltEntry> items = new List<BeltEntry>();
                    foreach (Item item in container.itemList) {
                        BeltEntry beltEntry = new BeltEntry {
                            ShortName = item.info.shortname, SkinID = item.skin, Amount = item.amount, Mods = new List<string>()
                        }
                        ;
                        if (item.GetHeldEntity() is BaseProjectile projectile && projectile?.primaryMagazine != null && projectile.primaryMagazine.ammoType != null) beltEntry.Ammo = projectile.primaryMagazine.ammoType.shortname;
                        if (item?.contents?.itemList != null) {
                            foreach (Item itemContent in item.contents.itemList) beltEntry.Mods.Add(itemContent.info.shortname);
                        }
                        items.Add(beltEntry);
                    }
                    return items;
                }
            }
            public class WearEntry {
                public string ShortName;
                public ulong SkinID;
                public static List<WearEntry> SaveItems(ItemContainer container) {
                    List<WearEntry> items = new List<WearEntry>();
                    foreach (Item item in container.itemList) {
                        items.Add(new WearEntry {
                            ShortName = item.info.shortname, SkinID = item.skin
                        }
                        );
                    }
                    return items;
                }
            }
            public void CacheConfig() {
                Parsed = new JObject {
                    ["Name"]
                    = Name, ["WearItems"] = new JArray {
                        WearItems.Select(x => new JObject {
                            ["ShortName"]
                            = x.ShortName, ["SkinID"] = x.SkinID
                        }
                        )
                    }
                    , ["BeltItems"] = new JArray {
                        BeltItems.Select(x => new JObject {
                            ["ShortName"]
                            = x.ShortName, ["Amount"] = x.Amount, ["SkinID"] = x.SkinID, ["Mods"] = new JArray {
                                x.Mods
                            }
                            , ["Ammo"] = x.Ammo
                        }
                        )
                    }
                    , ["Kit"] = Kit, ["Health"] = Health, ["RoamRange"] = RoamRange, ["ChaseRange"] = ChaseRange, ["SenseRange"] = SenseRange, ["ListenRange"] = SenseRange / 2f, ["AttackRangeMultiplier"] = AttackRangeMultiplier, ["CheckVisionCone"] = CheckVisionCone, ["VisionCone"] = VisionCone, ["HostileTargetsOnly"] = HostileTargetsOnly, ["DamageScale"] = DamageScale, ["TurretDamageScale"] = TurretDamageScale, ["AimConeScale"] = AimConeScale, ["DisableRadio"] = DisableRadio, ["CanRunAwayWater"] = CanRunAwayWater, ["CanSleep"] = CanSleep, ["SleepDistance"] = SleepDistance, ["Speed"] = Speed, ["AreaMask"] = !AboveOrUnderGround ? 1 : 25, ["AgentTypeID"] = !AboveOrUnderGround ? -1372625422 : 0, ["HomePosition"] = string.Empty, ["MemoryDuration"] = MemoryDuration, ["States"] = new JArray {
                        Stationary ? new HashSet<string> {
                            "IdleState", "CombatStationaryState"
                        }
                        : new HashSet<string> {
                            "RoamState", "CombatState", "ChaseState", "RaidState"
                        }
                    }
                }
                ;
            }
        }
#endregion
#region Lang
        protected override void LoadDefaultMessages() {
            lang.RegisterMessages(new Dictionary<string, string> {
                {
                    LangKeys.NoPermission, "Sorry you don't have permission to do that."
                }
                , {
                    LangKeys.Prefix, "<color=#8a916f>Guarded Crate</color>:\n"
                }
                , {
                    LangKeys.FailedToStartEvent, "Failed to start event."
                }
                , {
                    LangKeys.StartEvent, "Event starting."
                }
                , {
                    LangKeys.ClearEvents, "Cleaning up all running events."
                }
                , {
                    LangKeys.EventStart, "Special delivery is on its way to <color=#e7cf85>{0}</color> watch out it is heavily contested by guards, severity level <color=#e7cf85>{1}</color>.\nBe fast before the event ends in <color=#e7cf85>{2}</color>."
                }
                , {
                    LangKeys.EventCompleted, "<color=#e7cf85>{1}</color> has cleared the event at <color=#e7cf85>{0}</color>."
                }
                , {
                    LangKeys.EventEnded, "Event ended at <color=#e7cf85>{0}</color>; You were not fast enough; better luck next time!"
                }
                , {
                    LangKeys.EventNotFound, "Event not found, please make sure you have typed the correct name."
                }
                , {
                    LangKeys.EventIntersecting, "Another event is intersecting this position."
                }
                , {
                    LangKeys.EventPositionInvalid, "Event position invalid."
                }
                , {
                    LangKeys.EliminateGuards, "The crate is still contested eliminate all guards to gain access to high-valued loot."
                }
                , {
                    LangKeys.EventUpdated, "Event updated, please reload the plugin to take effect."
                }
                , {
                    LangKeys.InvalidGuardAmount, "Invalid guard amount must be between {0} - {1}."
                }
                , {
                    LangKeys.HelpStartEvent, "<color=#e7cf85>/{0}</color> start \"<color=#e7cf85><{1}></color>\", start an event of a specified type."
                }
                , {
                    LangKeys.HelpStopEvent, "<color=#e7cf85>/{0}</color> stop, stop all currently running events.\n\n"
                }
                , {
                    LangKeys.HelpHereEvent, "<color=#e7cf85>/{0}</color> here \"<color=#e7cf85><event-name></color>\", start an event at your position\n\n"
                }
                , {
                    LangKeys.HelpPositionEvent, "<color=#e7cf85>/{0}</color> position \"<color=#e7cf85><event-name></color>\" \"<color=#e7cf85>x y z</color>\", start an event at a specified position.\n\n"
                }
                , {
                    LangKeys.HelpLootEvent, "<color=#e7cf85>/{0}</color> loot \"<color=#e7cf85><event-name></color>\", create loot items that you wish to spawn in the crate, add the items to your inventory and run the command.\n\n"
                }
                , {
                    LangKeys.HelpGuardAmount, "<color=#e7cf85>/{0}</color> amount \"<color=#e7cf85><event-name></color>\", specify the guard amount to spawn.\n\n"
                }
                , {
                    LangKeys.HelpGuardLoadout, "<color=#e7cf85>/{0}</color> loadout \"<color=#e7cf85><event-name></color>\", set guard loadout using items in your inventory."
                }
            }
            , this);
        }
        private struct LangKeys {
            public const string Prefix = "Prefix";
            public const string NoPermission = "NoPermission";
            public const string FailedToStartEvent = "FailedToStartEvent";
            public const string ClearEvents = "ClearEvents";
            public const string StartEvent = "StartEvent";
            public const string EventCompleted = "EventCompleted";
            public const string EventStart = "EventStart";
            public const string EventEnded = "EventClear";
            public const string EventNotFound = "EventNotFound";
            public const string EventPositionInvalid = "EventPosInvalid";
            public const string EventIntersecting = "EventNearby";
            public const string EventUpdated = "EventUpdated";
            public const string EliminateGuards = "EliminateGuards";
            public const string InvalidGuardAmount = "InvalidGuardAmount";
            public const string HelpStartEvent = "HelpStartEvent";
            public const string HelpStopEvent = "HelpStopEvent";
            public const string HelpHereEvent = "HelpHereEvent";
            public const string HelpPositionEvent = "HelpPositionEvent";
            public const string HelpLootEvent = "HelpLootEvent";
            public const string HelpGuardAmount = "HelpGuardAmount";
            public const string HelpGuardLoadout = "HelpGuardLoadout";
        }
#endregion
#region Oxide Hooks
        private void OnServerInitialized() {
            SpawnManager.FindSpawnPoints();
            if (!string.IsNullOrEmpty(_configData.CommandName)) {
                cmd.AddConsoleCommand(_configData.CommandName, this, nameof(GuardedCrateConsoleCommand));
                cmd.AddChatCommand(_configData.CommandName, this, nameof(EventCommandCommands));
            }
            if (_configData.EnableAutoStart && _configData.AutoStartDuration > 0) timer.Every(_configData.AutoStartDuration, () => TryStartEvent(null));
        }
        private void Init() {
            permission.RegisterPermission(PERM_USE, this);
            _instance = this;
            LoadData();
            SpawnManager.Initialize();
        }
        private void Unload() {
            GuardedCrateManager.OnUnload();
            EntitiesCache.OnUnload();
            SpawnManager.OnUnload();
            _instance = null;
        }
        private void OnEntityDeath(ScientistNPC scientist, HitInfo info) {
            EntitiesCache.FindCrateInstance(scientist)?.OnGuardKilled(scientist, info?.InitiatorPlayer);
            EntitiesCache.RemoveEntity(scientist);
        }
        private void OnEntityKill(ScientistNPC scientist) {
            EntitiesCache.FindCrateInstance(scientist)?.OnGuardKilled(scientist, null);
            EntitiesCache.RemoveEntity(scientist);
        }
        private void OnEntityKill(LootContainer container) {
            EntitiesCache.FindCrateInstance(container)?.OnCrateKilled(container);
            EntitiesCache.RemoveEntity(container);
        }
        private void OnEntityKill(CargoPlane plane) {
            EntitiesCache.FindCrateInstance(plane)?.OnPlaneKilled(plane);
            EntitiesCache.RemoveEntity(plane);
        }
        private object CanHackCrate(BasePlayer player, HackableLockedCrate crate) {
            return EntitiesCache.FindCrateInstance(crate) ?.CanHackCrate(player);
        }
#endregion
#region Spawn Manager
        private static class SpawnManager {
            private static readonly LayerMask InterestedLayers = LayerMask.GetMask("Prevent_Building", "Vehicle_World", "Vehicle_Large", "Vehicle_Detailed");
            private static List<ZoneInfo> _ignoredZones;
            private static List<Collider> _tempColliders;
            private static List<Vector3> _spawnPoints;
            private static Coroutine _spawnRoutine;
            public static void Initialize() {
                _ignoredZones = new List<ZoneInfo>();
                _tempColliders = new List<Collider>();
                _spawnPoints = new List<Vector3>();
            }
            public static void OnUnload() {
                if (_spawnRoutine != null) ServerMgr.Instance.StopCoroutine(_spawnRoutine);
                _ignoredZones.Clear();
                _tempColliders.Clear();
                _spawnPoints.Clear();
                _ignoredZones = null;
                _tempColliders = null;
                _spawnPoints = null;
                _spawnRoutine = null;
            }
            public static void FindSpawnPoints() {
                if (_spawnRoutine != null) return;
                _spawnRoutine = ServerMgr.Instance.StartCoroutine(GenerateSpawnPoints(true));
            }
            private static IEnumerator GenerateSpawnPoints(bool exclusionZones, int attempts = 5000) {
                yield return null;
                if (exclusionZones && _instance._configData.ZoneManagerSettings.EnabledIgnoredZones) {
                    GetIgnoredZones();
                    yield return CoroutineEx.waitForEndOfFrame;
                    yield return CoroutineEx.waitForEndOfFrame;
                }
                float mapSizeX = TerrainMeta.Size.x / 2;
                float mapSizeZ = TerrainMeta.Size.z / 2;
                Vector3 spawnPoint = Vector3.zero;
                List<Vector3> list = Facepunch.Pool.Get<List<Vector3>>();
                for (int i = 0; i < attempts; i++) {
                    spawnPoint.x = UnityEngine.Random.Range(-mapSizeX, mapSizeX);
                    spawnPoint.z = UnityEngine.Random.Range(-mapSizeZ, mapSizeZ);
                    if (TestSpawnPoint(ref spawnPoint)) list.Add(spawnPoint);
                    if (i % 10 == 0) yield return CoroutineEx.waitForEndOfFrame;
                }
                _spawnPoints.AddRange(list);
                _tempColliders.Clear();
                Facepunch.Pool.FreeUnmanaged<Vector3>(ref list);
                Interface.Oxide.LogDebug("GuardedCrate: successfully found {0} spawn points.", _spawnPoints.Count);
                _spawnRoutine = null;
            }
            public static Vector3 GetSpawnPoint() {
                if (!(_spawnPoints?.Count > 0)) return Vector3.zero;
                for (int i = 0; i < 50; i++) {
                    Vector3 spawnPoint = _spawnPoints.GetRandom();
                    if (IsSpawnPointValid(spawnPoint)) return spawnPoint;
                    _spawnPoints.Remove(spawnPoint);
                    if (_spawnRoutine == null && _spawnPoints.Count < 50) _spawnRoutine = ServerMgr.Instance.StartCoroutine(GenerateSpawnPoints(false));
                }
                return Vector3.zero;
            }
            private static void GetIgnoredZones() {
                if (_instance._configData.ZoneManagerSettings?.IgnoredZones == null || _instance._configData.ZoneManagerSettings.IgnoredZones.Count == 0) return;
                if (_instance.ZoneManager == null || !_instance.ZoneManager.IsLoaded) return;
                string[] zoneIds = _instance?.ZoneManager.Call("GetZoneIDs") as string[];
                if (zoneIds == null) return;
                foreach (string zoneId in zoneIds) AddIgnoredZone(zoneId);
            }
            private static void AddIgnoredZone(string zoneId) {
                if (!_instance._configData.ZoneManagerSettings.IgnoredZones.Contains(zoneId)) return;
                if (_instance.ZoneManager.Call("GetZoneLocation", zoneId) is not Vector3 position || position == Vector3.zero) return;
                if (_instance.ZoneManager.Call("GetZoneRadius", zoneId) is not float radius) return;
                _ignoredZones.Add(new ZoneInfo(position, radius));
            }
            private static bool TestSpawnPoint(ref Vector3 spawnPoint) {
                if (!Physics.Raycast(spawnPoint + Vector3.up * 300f, Vector3.down, out RaycastHit hit, 400f, Layers.Solid) || hit.GetEntity() != null) return false;
                spawnPoint.y = hit.point.y;
                if (!ValidBounds.TestInnerBounds(spawnPoint)) return false;
                if (AntiHack.TestInsideTerrain(spawnPoint)) return false;
                if (AntiHack.IsInsideMesh(spawnPoint)) return false;
                if (IsIgnoredZone(spawnPoint)) return false;
                return !IsBlockedTopology(spawnPoint) && IsSpawnPointValid(spawnPoint);
            }
            private static bool IsBlockedTopology(Vector3 spawnPoint) {
                return (TerrainMeta.TopologyMap.GetTopology(spawnPoint) & (int)BLOCKED_TOPOLOGY) != 0;
            }
            private static bool IsIgnoredZone(Vector3 spawnPoint) {
                foreach (ZoneInfo zoneInfo in _ignoredZones) {
                    if (zoneInfo.IsInBounds(spawnPoint)) return true;
                }
                return false;
            }
            private static bool IsSpawnPointValid(Vector3 spawnPoint) {
                if (WaterLevel.Test(spawnPoint, true, true)) return false;
                try {
                    Vis.Colliders(spawnPoint, 15f, _tempColliders);
                    foreach (Collider collider in _tempColliders) {
                        if ((1 << collider.gameObject.layer & InterestedLayers) > 0) return false;
                        if (collider.name.Contains("radiation", CompareOptions.IgnoreCase)) return false;
                        if (collider.name.Contains("rock", CompareOptions.IgnoreCase)) return false;
                        if (collider.name.Contains("cliff", CompareOptions.IgnoreCase)) return false;
                        if (collider.name.Contains("fireball", CompareOptions.IgnoreCase) || collider.name.Contains("iceberg", CompareOptions.IgnoreCase) || collider.name.Contains("ice_sheet", CompareOptions.IgnoreCase)) return false;
                    }
                }
                finally {
                    _tempColliders.Clear();
                }
                List<BasePlayer> players = Facepunch.Pool.Get<List<BasePlayer>>();
                try {
                    Vis.Entities(spawnPoint, 150, players, Layers.Mask.Player_Server);
                    foreach (BasePlayer player in players) {
                        if (!player.IsSleeping() && !player.IsVisibleAndCanSee(spawnPoint)) return false;
                    }
                }
                finally {
                    Facepunch.Pool.FreeUnmanaged<BasePlayer>(ref players);
                }
                List<BaseEntity> entities = Facepunch.Pool.Get<List<BaseEntity>>();
                try {
                    Vis.Entities(spawnPoint, 150f, entities, Layers.PlayerBuildings);
                    if (entities.Count > 0) return false;
                }
                finally {
                    Facepunch.Pool.FreeUnmanaged<BaseEntity>(ref entities);
                }
                return true;
            }
        }
        private class ZoneInfo {
            public Vector3 Position;
            public float Radius;
            public ZoneInfo() {
            }
            public ZoneInfo(Vector3 position, float radius) {
                Position = position;
                Radius = radius;
            }
            public bool IsInBounds(Vector3 position) {
                return Vector3Ex.Distance2D(Position, position) <= Radius;
            }
        }
#endregion
#region Guarded Crate Manager
        private static class GuardedCrateManager {
            private static readonly List<GuardedCrateInstance> GuardedCrateInstances = new();
            public static void OnUnload() => CleanupInstances();
            public static bool HasIntersectingEvent(Vector3 position) {
                for (int i = 0; i < GuardedCrateInstances.Count; i++) {
                    GuardedCrateInstance crateInstance = GuardedCrateInstances[i];
                    if (crateInstance != null && Vector3Ex.Distance2D(crateInstance.transform.position, position) < 80f) return true;
                }
                return false;
            }
            public static void CleanupInstances() {
                for (int i = GuardedCrateInstances.Count - 1; i >= 0; i--) GuardedCrateInstances[i]?.EventEnded(true);
                GuardedCrateInstances.Clear();
            }
            public static void RegisterInstance(GuardedCrateInstance crateInstance) {
                GuardedCrateInstances.Add(crateInstance);
                _instance?.SubscribeToHooks(GuardedCrateInstances.Count);
            }
            public static void UnregisterInstance(GuardedCrateInstance crateInstance) {
                GuardedCrateInstances.Remove(crateInstance);
                _instance?.SubscribeToHooks(GuardedCrateInstances.Count);
            }
        }
#endregion
#region Guarded Crate Event
        private bool TryStartEvent(string eventName = null) {
            if (!NpcSpawn.IsPluginReady()) {
                PrintWarning("NpcSpawn not loaded please download from https://codefling.com");
                Interface.Oxide.UnloadPlugin(Name);
                return false;
            }
            Vector3 position = SpawnManager.GetSpawnPoint();
            if (position == Vector3.zero) {
                PrintWarning("Failed to find a valid spawn point.");
                return false;
            }
            EventEntry eventEntry = !string.IsNullOrEmpty(eventName) ? _storedData.FindEventByName(eventName) : _storedData.CrateEventEntries.GetRandom();
            if (eventEntry == null) {
                PrintWarning("Failed to find a valid event entry please check your configuration.");
                return false;
            }
            GuardedCrateInstance.CreateInstance(eventEntry, position);
            return true;
        }
        private class GuardedCrateInstance : MonoBehaviour {
            public List<BaseEntity> guardSpawnInstances = new();
            public MapMarkerGenericRadius markerSpawnInstance;
            public HackableLockedCrate crateSpawnInstance;
            public CargoPlane planeSpawnInstance;
            public GuardConfig guardConfig;
            public List<ItemEntry> lootTable;
            private EventState eventState;
            public string eventName;
            public float eventSeconds = 120f;
            public bool enableLockToPlayer;
            public bool enableClanTag;
            public bool enableAutoHack;
            public float hackSeconds;
            public bool enableMarker;
            public Color markerColor1;
            public Color markerColor2;
            public float markerRadius;
            public float markerOpacity;
            public bool enableEliminateGuards;
            public int guardAmount;
            public bool enableLootTable;
            public int minLootAmount;
            public int maxLootAmount;
            public float thinkEvery = 1f;
            public float lastThinkTime;
            public float timePassed;
            public bool timeEnded;
            public static void CreateInstance(EventEntry eventEntry, Vector3 position) {
                if (eventEntry.GuardConfig.Parsed == null) eventEntry.GuardConfig.CacheConfig();
                GuardedCrateInstance crateInstance = CustomUtils.CreateObjectWithComponent<GuardedCrateInstance>(position, Quaternion.identity, "Guarded_Create_Event");
                crateInstance.gameObject.AddComponent<SphereCollider>().radius = 15f;
                crateInstance.eventName = eventEntry.EventName;
                crateInstance.eventSeconds = eventEntry.EventDuration;
                crateInstance.enableLockToPlayer = eventEntry.EnableLockToPlayer;
                crateInstance.enableClanTag = eventEntry.EnableClanTag;
                crateInstance.enableAutoHack = eventEntry.EnableAutoHack;
                crateInstance.hackSeconds = eventEntry.HackSeconds;
                crateInstance.enableMarker = eventEntry.EnableMarker;
                crateInstance.markerColor1 = CustomUtils.GetColor(eventEntry.MapMarkerColor1);
                crateInstance.markerColor2 = CustomUtils.GetColor(eventEntry.MapMarkerColor2);
                crateInstance.markerRadius = eventEntry.MapMarkerRadius;
                crateInstance.markerOpacity = eventEntry.MapMarkerOpacity;
                crateInstance.enableLootTable = eventEntry.EnableLootTable;
                crateInstance.lootTable = eventEntry.LootTable;
                crateInstance.minLootAmount = eventEntry.LootMinAmount;
                crateInstance.maxLootAmount = eventEntry.LootMaxAmount;
                crateInstance.enableEliminateGuards = eventEntry.EnableEliminateGuards;
                crateInstance.guardConfig = eventEntry.GuardConfig;
                crateInstance.guardAmount = eventEntry.GuardAmount;
                crateInstance.EventStartup();
                GuardedCrateManager.RegisterInstance(crateInstance);
            }
            public static void RemoveInstance(GuardedCrateInstance crateInstance) {
                GuardedCrateManager.UnregisterInstance(crateInstance);
                if (crateInstance?.gameObject != null) UnityEngine.GameObject.DestroyImmediate(crateInstance.gameObject);
            }
#region Unity
            private void FixedUpdate() {
                if (lastThinkTime < thinkEvery) {
                    lastThinkTime += UnityEngine.Time.deltaTime;
                }
                else {
                    if (timeEnded) return;
                    timePassed += lastThinkTime;
                    if (timePassed >= eventSeconds) {
                        timeEnded = true;
                        EventFailed();
                        return;
                    }
                    lastThinkTime = 0.0f;
                }
            }
#endregion
#region Setup / Destroy
            private IEnumerator Initialize() {
                yield return CoroutineEx.waitForEndOfFrame;
                eventState = EventState.Active;
                yield return SpawnPlane();
                Notification.MessagePlayers(LangKeys.EventStart, MapHelper.PositionToString(transform.position), eventName, eventSeconds.ToStringTime());
            }
            public void Dispose() {
                StopAllCoroutines();
                CancelInvoke();
                ClearEntities();
                GuardedCrateInstance.RemoveInstance(this);
            }
#endregion
#region Management
            public void EventStartup() {
                enabled = true;
                eventState = EventState.Starting;
                StartCoroutine(Initialize());
                Interface.Oxide.CallHook("OnGuardedCrateEventStart", transform.position);
            }
            public void EventComplete(BasePlayer player) {
                if (eventState != EventState.Active) return;
                eventState = EventState.Completed;
                EventWinner(player);
                UnlockCrates();
                EventEnded();
            }
            public void EventFailed() {
                eventState = EventState.Failed;
                Interface.Oxide.CallHook("OnGuardedCrateEventFailed", transform.position);
                Notification.MessagePlayers(LangKeys.EventEnded, MapHelper.PositionToString(transform.position));
                EventEnded(true);
            }
            public void EventEnded(bool forced = false) => Dispose();
            private void EventWinner(BasePlayer player) {
                if (player == null) return;
                string displayName = player.displayName;
                if (enableClanTag) {
                    if (_instance != null && _instance.Clans.IsPluginReady()) displayName = string.Format("[{0}]{1}", _instance.Clans.Call<string>("GetClanOf", player.userID), displayName);
                }
                if (enableLockToPlayer) {
                    if (_instance != null && _instance.HackableLock.IsPluginReady()) _instance.HackableLock.Call("LockCrateToPlayer", player, crateSpawnInstance);
                }
                Interface.CallHook("OnGuardedCrateEventEnded", player, crateSpawnInstance);
                Notification.MessagePlayers(LangKeys.EventCompleted, MapHelper.PositionToString(transform.position), displayName);
            }
            private void UnlockCrates() {
                if (eventState != EventState.Completed) return;
                if (enableAutoHack) crateSpawnInstance.StartHacking();
                crateSpawnInstance.shouldDecay = true;
                crateSpawnInstance.RefreshDecay();
            }
#endregion
#region Spawning
            public IEnumerator SpawnEntities() {
                yield return CoroutineEx.waitForEndOfFrame;
                yield return SpawnMarker();
                yield return SpawnCrate();
                yield return SpawnGuards();
            }
            private IEnumerator SpawnPlane() {
                yield return CoroutineEx.waitForEndOfFrame;
                planeSpawnInstance = (CargoPlane)GameManager.server.CreateEntity(PLANE_PREFAB);
                planeSpawnInstance.InitDropPosition(transform.position);
                planeSpawnInstance.Spawn();
                planeSpawnInstance.secondsTaken = 0f;
                planeSpawnInstance.secondsToTake = 30f;
                planeSpawnInstance.gameObject.AddComponent<CargoPlaneComponent>().guardedCrate = this;
                EntitiesCache.CreateEntity(planeSpawnInstance, this);
            }
            private IEnumerator SpawnGuards() {
                yield return CoroutineEx.waitForEndOfFrame;
                if (_instance == null || !_instance.NpcSpawn.IsPluginReady()) {
                    Interface.Oxide.LogDebug("NpcSpawn not loaded, please load the plugin.");
                    yield break;
                }
                for (int i = 0; i < guardAmount; i++) {
                    Vector3 position = transform.position.GetPointAround(10551297, 5f, (360f / guardAmount) * i);
                    yield return SpawnGuard(position);
                }
            }
            private IEnumerator SpawnGuard(Vector3 position) {
                yield return CoroutineEx.waitForEndOfFrame;
                guardConfig.Parsed["HomePosition"] = position.ToString();
                ScientistNPC entity = (ScientistNPC)_instance?.NpcSpawn.Call("SpawnNpc", position, guardConfig.Parsed);
                guardSpawnInstances.Add(entity);
                EntitiesCache.CreateEntity(entity, this);
            }
            private IEnumerator SpawnMarker() {
                yield return CoroutineEx.waitForEndOfFrame;
                if (!enableMarker) yield break;
                markerSpawnInstance = CustomUtils.CreateEntity<MapMarkerGenericRadius>(MARKER_PREFAB, transform.position, Quaternion.identity);
                markerSpawnInstance.EnableSaving(false);
                markerSpawnInstance.color1 = markerColor1;
                markerSpawnInstance.color2 = markerColor2;
                markerSpawnInstance.radius = markerRadius;
             
// ... [Code preview truncated due to length. Full source in attached file] ...

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