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

FREE BankHeist : 1.5.21 1.5.21

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
/*
 * Copyright (c) 2023 Bazz3l
 *
 * Bank Heist cannot be copied, edited and/or (re)distributed without the express permission of Bazz3l.* Discord 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.*
 */
// Reference: Unity.AI.Navigation
using System.Collections.Generic;
using System.Collections;
using System.Diagnostics;
using System.Text;
using System.Linq;
using System;
using Oxide.Plugins.BankHeistExtensionMethods;
using Oxide.Core.Plugins;
using Oxide.Core;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Network;
using ProtoBuf;
using Rust;
using Unity.AI.Navigation;
using UnityEngine;
using UnityEngine.AI;
namespace Oxide.Plugins {
    [Info("Bank Heist", "Bazz3l", "1.5.21")]
    [Description("")]
    internal class BankHeist : RustPlugin {
        [PluginReference]
        Plugin NpcSpawn, PersonalVaultDoor;
#region Fields
        private const int RAYCAST_LAYERS = Layers.Solid | Layers.Deploy;
        private const string WORKER_PERM = "bankheist.worker";
        private const string MANAGE_PERM = "bankheist.manage";
        private readonly HashSet<BaseEntity> _tempSpawned = new();
        private readonly HashSet<ulong> _players = new();
        private readonly object _falseObj = false;
        private readonly object _trueObj = true;
        private ConfigData _configData;
        private Coroutine _coroutine;
        private static BankHeist _instance;
#endregion
#region Local
        protected override void LoadDefaultMessages() {
            lang.RegisterMessages(new Dictionary<string, string> {
                {
                    LangEntry.NoPermission, "You don't have permission to use this command."
                }
                , {
                    LangEntry.PrefabsToSpawn, "Prefab list:\n{0}"
                }
                , {
                    LangEntry.InvalidArgs, "Invalid arguments:"
                }
                , {
                    LangEntry.InvalidArgument, "Invalid argument: {0} must be a {1}"
                }
                , {
                    LangEntry.InvalidCmd, "Invalid command: /{0} {1} {2}"
                }
                , {
                    LangEntry.InvalidLookPoint, "Invalid look point."
                }
                , {
                    LangEntry.EntityNotFound, "No entity found at the look position."
                }
                , {
                    LangEntry.MonumentNotFound, "No monument found by that name."
                }
                , {
                    LangEntry.SpawnEntryNotFound, "No spawn entry found."
                }
                , {
                    LangEntry.BankAlreadyExists, "A bank already exists by that name."
                }
                , {
                    LangEntry.BankNotFound, "No bank found by that name."
                }
                , {
                    LangEntry.BankCreated, "Bank created successfully, if you wish to parent the event to a specific monument do so now and reload the plugin."
                }
                , {
                    LangEntry.BankRemoved, "Bank removed successfully!"
                }
                , {
                    LangEntry.BankUpdated, "Bank updated successfully!"
                }
                , {
                    LangEntry.BankParent, "Bank parent updated successfully, please reload the plugin."
                }
                , {
                    LangEntry.BankNotSpawned, "No bank spawned by that name."
                }
                , {
                    LangEntry.BankAttacked, "<color=#ca094c>WARNING!</color>!\n<color=#2ec8d0>{0}</color> is being attacked please send help!"
                }
                , {
                    LangEntry.ProfileAlreadyExists, "A profile already exists by that name."
                }
                , {
                    LangEntry.ProfileNotFound, "No profile found by that name."
                }
                , {
                    LangEntry.ProfileCreated, "Profile created successfully!"
                }
                , {
                    LangEntry.ProfileRemoved, "Profile removed successfully!"
                }
                , {
                    LangEntry.ProfileUpdated, "Profile updated successfully!"
                }
                , {
                    LangEntry.DebugInvalidSyntax, "<color=#2ec8d0>Debug</color>: invalid syntax, /bhm debug <bank-name> <door|loot|guard|info|everything>."
                }
                , {
                    LangEntry.DebugToggled, "<color=#2ec8d0>Debug</color>: has now been enabled for (<color=#2ec8d0>30</color>) seconds."
                }
                , {
                    LangEntry.DebugInvalidOption, "<color=#2ec8d0>Debug</color>: invalid option specified."
                }
                , {
                    LangEntry.EliminateGuards, "You must first eliminate all guards."
                }
                , {
                    LangEntry.OnUnauthorizedAccess, "You don't have access to this door, blowup the door to gain access."
                }
                , {
                    LangEntry.OnCratesLooted, "<color=#2ec8d0>{0}</color> has been robbed of all loot."
                }
                , {
                    LangEntry.OnGuardDeath, "<color=#2ec8d0>{0}</color>: security guard down <color=#2ec8d0>{1}</color>/<color=#2ec8d0>{2}</color> remaining!"
                }
                , {
                    LangEntry.OnDoorDeath, "<color=#2ec8d0>{0}</color>: security door breached!"
                }
                , {
                    LangEntry.OnEnterZone, "You have entered <color=#2ec8d0>{0}</color>"
                }
                , {
                    LangEntry.OnLeaveZone, "You have left <color=#2ec8d0>{0}</color>"
                }
                , {
                    LangEntry.OnCommandBlocked, "You cannot use this command from this location!"
                }
                , {
                    LangEntry.OnTeleportBlocked, "You cannot teleport from this location!"
                }
                , {
                    LangEntry.OnWorkerPreventLoot, "You cannot loot this container."
                }
                , {
                    LangEntry.OnBankReset, "<color=#2ec8d0>{0}</color> is now available."
                }
                ,
            }
            , this);
        }
        private static class LangEntry {
            public static readonly string NoPermission = "NoPermission";
            public static readonly string PrefabsToSpawn = "PrefabsToSpawn";
            public static readonly string InvalidArgs = "InvalidArgs";
            public static readonly string InvalidArgument = "InvalidArgument";
            public static readonly string InvalidCmd = "InvalidCmd";
            public static readonly string InvalidLookPoint = "InvalidLookPoint";
            public static readonly string MonumentNotFound = "MonumentNotFound";
            public static readonly string EntityNotFound = "EntityNotFound";
            public static readonly string SpawnEntryNotFound = "SpawnEntryNotFound";
            public static readonly string BankAlreadyExists = "BankAlreadyExists";
            public static readonly string BankNotFound = "BankNotFound";
            public static readonly string BankCreated = "BankCreated";
            public static readonly string BankRemoved = "BankRemoved";
            public static readonly string BankUpdated = "BankUpdated";
            public static readonly string BankParent = "BankParent";
            public static readonly string BankAttacked = "BankAttacked";
            public static readonly string BankNotSpawned = "BankNotSpawned";
            public static readonly string ProfileAlreadyExists = "ProfileAlreadyExists";
            public static readonly string ProfileNotFound = "ProfileNotFound";
            public static readonly string ProfileCreated = "ProfileCreated";
            public static readonly string ProfileRemoved = "ProfileRemoved";
            public static readonly string ProfileUpdated = "ProfileUpdated";
            public static readonly string DebugInvalidSyntax = "DebugInvalidSyntax";
            public static readonly string DebugInvalidOption = "DebugInvalidOption";
            public static readonly string DebugToggled = "DebugToggled";
            public static readonly string EliminateGuards = "EliminateGuards";
            public static readonly string OnUnauthorizedAccess = "OnUnauthorizedAccess";
            public static readonly string OnCratesLooted = "OnCratesLooted";
            public static readonly string OnGuardDeath = "OnGuardDeath";
            public static readonly string OnDoorDeath = "OnDoorDeath";
            public static readonly string OnEnterZone = "OnEnterZone";
            public static readonly string OnLeaveZone = "OnLeaveZone";
            public static readonly string OnCommandBlocked = "OnCommandBlocked";
            public static readonly string OnTeleportBlocked = "OnTeleportBlocked";
            public static readonly string OnWorkerPreventLoot = "OnWorkerPreventLoot";
            public static readonly string OnBankReset = "OnBankBankReset";
        }
        private string GetMessage(string langEntry, string userID = null, params object[] args) {
            return args?.Length > 0 ? string.Format(lang.GetMessage(langEntry, this, userID), args) : lang.GetMessage(langEntry, this, userID);
        }
        private void MessagePlayer(BasePlayer player, string langEntry, params object[] args) {
            if (player == null || !player.IsConnected) return;
            player.ChatMessage(GetMessage(langEntry, player.UserIDString, args));
        }
        private void MessagePlayers(string langEntry, params object[] args) {
            ConsoleNetwork.BroadcastToAllClients("chat.add", 2, 0, GetMessage(langEntry, null, args));
        }
#endregion
#region Config
        protected override void LoadDefaultConfig() => _configData = ConfigData.DefaultConfig();
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                _configData = Config.ReadObject<ConfigData>();
                if (_configData == null) throw new Exception();
                if (_configData.SpawnablePrefabs == null) {
                    _configData.SpawnablePrefabs = ConfigData.DefaultConfig().SpawnablePrefabs;
                    SaveConfig();
                }
            }
            catch (Exception e) {
                PrintWarning("Loaded default config: {0}", e.Message);
                LoadDefaultConfig();
            }
        }
        protected override void SaveConfig() => Config.WriteObject(_configData, true);
        private class ConfigData {
            [JsonProperty("enable notifications")]
            public bool EnableNotifications;
            [JsonProperty("enable visible bubble")]
            public bool EnableVisibleBubble;
            [JsonProperty("enable visible marker")]
            public bool EnableVisibleMarker;
            [JsonProperty("enable alarm trigger")]
            public bool EnableAlarmTrigger;
            [JsonProperty("enable eliminate guards")]
            public bool MustEliminateGuards;
            [JsonProperty("enable zone messages")]
            public bool EnableZoneMessages;
            [JsonProperty("prevent worker looting bank")]
            public bool PreventWorkerLootingBank;
            [JsonProperty("prevent teleport from bank")]
            public bool PreventTeleportFromBank;
            [JsonProperty("blocked zone commands")]
            public List<string> BlockedCommands;
            [JsonProperty("spawnable prefabs")]
            public Dictionary<string, string> SpawnablePrefabs;
            public static ConfigData DefaultConfig() {
                return new ConfigData {
                    EnableNotifications = true, EnableVisibleBubble = true, EnableVisibleMarker = true, EnableAlarmTrigger = true, EnableZoneMessages = true, MustEliminateGuards = true, PreventTeleportFromBank = false, BlockedCommands = new List<string>(), SpawnablePrefabs = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) {
                        {
                            "garage-door", "assets/prefabs/building/wall.frame.garagedoor/wall.frame.garagedoor.prefab"
                        }
                        , {
                            "vault-door", "assets/bundled/prefabs/modding/asset_store/bankheist_package/bankheist_vol03/prefabs/door.vault.static.prefab"
                        }
                        , {
                            "toptier-door", "assets/prefabs/building/door.hinged/door.hinged.toptier.prefab"
                        }
                        , {
                            "toptier-d-door", "assets/prefabs/building/door.double.hinged/door.double.hinged.toptier.prefab"
                        }
                        , {
                            "hackable-crate", "assets/prefabs/deployable/chinooklockedcrate/codelockedhackablecrate.prefab"
                        }
                        , {
                            "elite-crate", "assets/bundled/prefabs/radtown/crate_elite.prefab"
                        }
                        , {
                            "crate-normal", "assets/bundled/prefabs/radtown/crate_normal.prefab"
                        }
                        , {
                            "crate-normal_2", "assets/bundled/prefabs/radtown/crate_normal_2.prefab"
                        }
                    }
                }
                ;
            }
        }
#endregion
#region Bank Storage
        private class BaseStorage<T> where T : BaseStorage<T>, new() {
            public static T Data;
            public static string Filename;
            public static void LoadData(string filename) {
                Filename = filename;
                try {
                    Data = Interface.Oxide.DataFileSystem.ReadObject<T>(Filename);
                    if (Data == null) throw new Exception();
                }
                catch {
                    Interface.Oxide.LogDebug("Failed to load {0}; loaded default data.", Filename);
                    Data = new T();
                }
            }
            public static void SaveData() {
                if (Data == null) return;
                Interface.Oxide.DataFileSystem.WriteObject(Filename, Data);
            }
            public static void OnUnload() {
                Data = null;
                Filename = null;
            }
        }
        private class BankStorage : BaseStorage<BankStorage> {
            public List<BankEntry> BankEntries = new();
            public bool GetBankByName(string displayName, out BankEntry foundEntry) {
                for (int i = 0; i < BankEntries.Count; i++) {
                    BankEntry bankEntry = BankEntries[i];
                    if (bankEntry != null && bankEntry.DisplayName.Equals(displayName, StringComparison.OrdinalIgnoreCase)) {
                        foundEntry = bankEntry;
                        return true;
                    }
                }
                foundEntry = null;
                return false;
            }
        }
        private class BankEntry {
            [JsonProperty("bank display name")]
            public string DisplayName;
            [JsonProperty("parent monument name")]
            public string MonumentParentName;
            [JsonProperty("time between resets")]
            public float TimeBetweenResets;
            [JsonProperty("alarm disable when all crates are looted")]
            public bool AlarmClear;
            [JsonProperty("alarm timeout seconds")]
            public float AlarmTimeoutSeconds;
            [JsonProperty("spawn position")]
            public Vector3 SpawnPosition;
            [JsonProperty("spawn rotation")]
            public Vector3 SpawnRotation;
            [JsonProperty("player detection origin")]
            public Vector3 PlayerDetectionOrigin;
            [JsonProperty("player detection radius")]
            public float PlayerDetectionRadius;
            [JsonProperty("map marker origin")]
            public Vector3 MapMarkerOrigin;
            [JsonProperty("map marker radius")]
            public float MapMarkerRadius;
            [JsonProperty("map marker opacity")]
            public float MapMarkerOpacity;
            [JsonProperty("map marker ready color")]
            public string MapMarkerReadyColor;
            [JsonProperty("map marker reset color")]
            public string MapMarkerResetColor;
            [JsonProperty("map marker outline color")]
            public string MapMarkerOuterColor;
            [JsonProperty("loot spawn group entries")]
            public List<SpawnEntry> LootSpawnGroupEntries;
            [JsonProperty("door spawn group entries")]
            public List<SpawnEntry> DoorSpawnGroupEntries;
            [JsonProperty("npcs spawn group entries")]
            public List<SpawnEntry> NpcSpawnGroupEntries;
            public BankEntry() {
            }
            public BankEntry(string displayName, Transform transform) {
                DisplayName = displayName;
                TimeBetweenResets = 1800f;
                SpawnPosition = transform.position;
                SpawnRotation = new Vector3(0.0f, transform.rotation.eulerAngles.y, 0.0f);
                PlayerDetectionOrigin = Vector3.zero;
                PlayerDetectionRadius = 100f;
                MapMarkerOrigin = Vector3.zero;
                MapMarkerRadius = 100f;
                MapMarkerOpacity = 0.6f;
                MapMarkerReadyColor = "#2eff74";
                MapMarkerResetColor = "#ff2e2e";
                MapMarkerOuterColor = "#ffffff";
                LootSpawnGroupEntries = new List<SpawnEntry>();
                DoorSpawnGroupEntries = new List<SpawnEntry>();
                NpcSpawnGroupEntries = new List<SpawnEntry>();
            }
            public IEnumerator SpawnBankInstance() {
                Vector3 spawnPosition = SpawnPosition;
                Vector3 spawnRotation = SpawnRotation;
                if (!string.IsNullOrEmpty(MonumentParentName)) {
                    Transform transform = MonumentCache.FindMonumentByName(MonumentParentName)?.GetTransform();
                    ;
                    if (transform == null) {
                        Interface.Oxide.LogDebug("Failed to perform setup: missing parent transform for ({0}) assigned to ({1}).", MonumentParentName, DisplayName);
                        yield break;
                    }
                    spawnPosition = transform.position;
                    spawnRotation = transform.rotation.eulerAngles;
                }
                if (LootSpawnGroupEntries == null || DoorSpawnGroupEntries == null || NpcSpawnGroupEntries == null) {
                    Interface.Oxide.LogDebug("Failed to perform setup: missing spawn group found in data file for ({0}).", DisplayName);
                    yield break;
                }
                // Create bank component
                BankHeistInstance component = CustomUtils.CreateObjectWithComponent<BankHeistInstance>(spawnPosition, Quaternion.Euler(spawnRotation), "BANK_CONTROLLER_NAME");
                // Cache instance
                BankHeistInstance.CacheHeistInstance(component);
                // General settings
                component.requiresReset = true;
                component.displayName = DisplayName;
                component.monumentName = MonumentParentName;
                component.timeBetweenResets = TimeBetweenResets;
                component.alarmTime = AlarmTimeoutSeconds;
                component.clearAlarm = AlarmClear;
                // Player detection origin and radius
                component.playerDetectionOrigin = component.transform.TransformPoint(PlayerDetectionOrigin);
                component.playerDetectionRadius = PlayerDetectionRadius / 2;
                // Player detection sphere collider
                SphereCollider sphereCollider = component.gameObject.AddComponent<SphereCollider>();
                sphereCollider.isTrigger = true;
                sphereCollider.radius = PlayerDetectionRadius / 2;
                sphereCollider.center = PlayerDetectionOrigin;
                // Map marker origin and radius
                component.markerOrigin = component.transform.TransformPoint(MapMarkerOrigin);
                component.markerReadyColor = ColorUtility.TryParseHtmlString(MapMarkerReadyColor, out Color readyColor) ? readyColor : Color.green;
                component.markerResetColor = ColorUtility.TryParseHtmlString(MapMarkerResetColor, out Color resetColor) ? resetColor : Color.red;
                component.markerOuterColor = ColorUtility.TryParseHtmlString(MapMarkerOuterColor, out Color outerColor) ? outerColor : Color.white;
                component.markerRadius = MapMarkerRadius / 2;
                component.markerOpacity = MapMarkerOpacity;
                // Loot spawn group
                component.lootSpawnGroup = component.gameObject.AddComponent<LootSpawnGroup>();
                component.lootSpawnGroup.spawnPointEntries.AddRange(LootSpawnGroupEntries ?? new List<SpawnEntry>());
                component.lootSpawnGroup.bankHeistInstance = component;
                // Door spawn group
                component.doorSpawnGroup = component.gameObject.AddComponent<DoorSpawnGroup>();
                component.doorSpawnGroup.spawnPointEntries.AddRange(DoorSpawnGroupEntries ?? new List<SpawnEntry>());
                component.doorSpawnGroup.bankHeistInstance = component;
                // Guard spawn group
                component.guardSpawnGroup = component.gameObject.AddComponent<GuardSpawnGroup>();
                component.guardSpawnGroup.spawnPointEntries.AddRange(NpcSpawnGroupEntries ?? new List<SpawnEntry>());
                component.guardSpawnGroup.bankHeistInstance = component;
                // Initialize event
                yield return component.Initialize();
            }
        }
        private class SpawnEntry {
            public int Id;
            public string Prefab;
            public string Profile;
            public Vector3 Position;
            public Vector3 Rotation;
            public SpawnEntry() {
            }
            public SpawnEntry(int id, string prefab, string profile, Vector3 position, Vector3 rotation, ulong skinID = 0UL) {
                Id = id;
                Prefab = prefab;
                Profile = profile;
                Position = position;
                Rotation = rotation;
            }
            public T CreateEntity<T>(Transform transform) where T : BaseEntity {
                Vector3 position = transform.TransformPoint(Position);
                Vector3 rotation = Rotation;
                rotation.y = transform.rotation.eulerAngles.y + rotation.y;
                return (T)GameManager.server.CreateEntity(Prefab, position, Quaternion.Euler(rotation), false);
            }
            public T CreateGuard<T>(Transform transform, GuardProfileEntry profileEntry) where T : BaseEntity {
                Vector3 position = transform.TransformPoint(Position);
                if (profileEntry.Parsed == null) profileEntry.CacheConfig();
                return (T)_instance?.NpcSpawn?.Call("SpawnNpc", position, profileEntry.Parsed);
            }
        }
#endregion
#region Guard Profile Storage
        private class GuardProfileStorage : BaseStorage<GuardProfileStorage> {
            public Dictionary<string, GuardProfileEntry> ProfileEntries = new(StringComparer.OrdinalIgnoreCase);
            public bool GetProfileByName(string profileName, out GuardProfileEntry profileEntry) {
                if (string.IsNullOrEmpty(profileName)) {
                    profileEntry = null;
                    return false;
                }
                return ProfileEntries.TryGetValue(profileName, out profileEntry);
            }
            public static GuardProfileEntry DefaultProfile() {
                return new GuardProfileEntry {
                    Name = "Bank Guard", WearItems = new List<GuardProfileEntry.WearEntry> {
                        new() {
                            ShortName = "hazmatsuit_scientist_peacekeeper", SkinID = 0UL
                        }
                    }
                    , BeltItems = new List<GuardProfileEntry.BeltEntry> {
                        new() {
                            ShortName = "smg.mp5", Amount = 1, SkinID = 0UL, Ammo = null, Mods = new List<string>()
                        }
                        , new() {
                            ShortName = "syringe.medical", Amount = 10, SkinID = 0UL, Ammo = null, Mods = new List<string>()
                        }
                        ,
                    }
                    , Kit = "", Health = 250f, RoamRange = 5f, ChaseRange = 25f, SenseRange = 75f, ListenRange = 75f / 2, AttackRangeMultiplier = 8f, CheckVisionCone = false, VisionCone = 180f, DamageScale = 1f, TurretDamageScale = 0.25f, AimConeScale = 0.35f, DisableRadio = false, CanRunAwayWater = true, CanSleep = false, Speed = 8.5f, HomePosition = string.Empty, MemoryDuration = 30f, Stationary = false, UseUnderGround = false
                }
                ;
            }
        }
        private class GuardProfileEntry {
            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 ListenRange;
            public float AttackRangeMultiplier;
            public bool CheckVisionCone;
            public float VisionCone;
            public bool HostileTargetsOnly;
            public float DamageScale;
            public float TurretDamageScale;
            public float AimConeScale;
            public bool DisableRadio;
            public bool CanRunAwayWater;
            public bool CanSleep;
            public float SleepDistance;
            public float Speed;
            public int AreaMask;
            public int AgentTypeID;
            [JsonIgnore]
            public string HomePosition;
            public float MemoryDuration;
            public bool Stationary;
            public bool UseUnderGround;
            public HashSet<string> States;
            [JsonIgnore]
            public JObject Parsed;
            public class BeltEntry {
                public string ShortName;
                public int Amount;
                public ulong SkinID;
                public List<string> Mods;
                public string Ammo;
                public static BeltEntry SerializeItem(Item item) {
                    BeltEntry wearEntry = new BeltEntry {
                        ShortName = item.info.shortname, SkinID = item.skin, Amount = item.amount, Mods = new List<string>()
                    }
                    ;
                    if (item.GetHeldEntity() is BaseProjectile projectile && projectile.primaryMagazine?.ammoType != null) wearEntry.Ammo = projectile.primaryMagazine.ammoType.shortname;
                    if (item.contents?.itemList == null) return wearEntry;
                    foreach (Item itemContent in item.contents.itemList) wearEntry.Mods.Add(itemContent.info.shortname);
                    return wearEntry;
                }
            }
            public class WearEntry {
                public string ShortName;
                public ulong SkinID;
                public static WearEntry SerializeItem(Item item) {
                    return new WearEntry {
                        ShortName = item.info.shortname, SkinID = item.skin
                    }
                    ;
                }
            }
            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"] = !UseUnderGround ? 1 : 25, ["AgentTypeID"] = !UseUnderGround ? -1372625422 : 0, ["HomePosition"] = string.Empty, ["MemoryDuration"] = MemoryDuration, ["States"] = new JArray {
                        Stationary ? new HashSet<string> {
                            "IdleState", "CombatStationaryState"
                        }
                        : new HashSet<string> {
                            "RoamState", "ChaseState", "CombatState", "RaidState"
                        }
                    }
                }
                ;
            }
        }
#endregion
#region Loot Profile Storage
        private class LootProfileStorage : BaseStorage<LootProfileStorage> {
            public Dictionary<string, LootProfileEntry> ProfileEntries = new(StringComparer.OrdinalIgnoreCase);
            public bool GetProfileByName(string profileName, out LootProfileEntry foundEntry) {
                if (string.IsNullOrEmpty(profileName)) {
                    foundEntry = null;
                    return false;
                }
                return ProfileEntries.TryGetValue(profileName, out foundEntry);
            }
            public static LootProfileEntry DefaultProfile() {
                return new LootProfileEntry {
                    MinItems = 1, MaxItems = 1, SkinId = 0UL, HackableSeconds = 300f, LootItems = new List<LootProfileEntry.LootItem>()
                }
                ;
            }
        }
        private class LootProfileEntry {
            public int MinItems = 1;
            public int MaxItems = 1;
            public ulong SkinId = 0UL;
            public float HackableSeconds = 300f;
            public List<LootItem> LootItems = new();
            public class LootItem {
                public string Shortname;
                public string ItemName = string.Empty;
                public ulong SkinID;
                public int MinAmount = 1;
                public int MaxAmount = 1;
                public bool IsBlueprint;
                [JsonIgnore]
                private int _itemId = -1;
                [JsonIgnore]
                public int ItemID {
                    get {
                        if (_itemId == -1) _itemId = ItemManager.FindItemDefinition(Shortname)?.itemid ?? -1;
                        return _itemId;
                    }
                }
                public LootItem() {
                }
                public LootItem(Item item) {
                    Shortname = item.info.shortname;
                    ItemName = item.name;
                    SkinID = item.skin;
                    MinAmount = item.amount;
                    MaxAmount = item.amount;
                    IsBlueprint = item.blueprintTarget != 0;
                }
                public void CreateItem(LootContainer container) {
                    if (ItemID == -1) {
                        _instance?.Puts($"[BankHeist] - Failed to find ItemDefinition for {Shortname}!");
                        return;
                    }
                    Item item;
                    if (IsBlueprint) {
                        item = ItemManager.CreateByItemID(-996920608, UnityEngine.Random.Range(MinAmount, MaxAmount), SkinID);
                        item.blueprintTarget = ItemID;
                    }
                    else {
                        item = ItemManager.CreateByItemID(ItemID, UnityEngine.Random.Range(MinAmount, MaxAmount), SkinID);
                        item.name = ItemName;
                    }
                    if (!item.MoveToContainer(container.inventory)) item.Remove();
                }
            }
            public void GenerateContainerItems(ref List<LootItem> items, int maxItemCount) {
                for (int i = 0; i < 100; i++) {
                    LootItem lootItem = LootItems[UnityEngine.Random.Range(0, LootItems.Count)];
                    if (!items.Contains(lootItem)) items.Add(lootItem);
                    if (items.Count >= maxItemCount) break;
                }
            }
            public void PopulateContainer(LootContainer container, int itemCount) {
                if (LootItems == null || LootItems.Count == 0) return;
                List<LootItem> items = Facepunch.Pool.Get<List<LootItem>>();
                try {
                    container.inventory.SafeClear();
                    GenerateContainerItems(ref items, Mathf.Clamp(itemCount, 1, 24));
                    container.inventory.capacity = items.Count;
                    foreach (LootItem lootItem in items) lootItem.CreateItem(container);
                }
                catch (Exception e) {
                    //
                }
                Facepunch.Pool.FreeUnmanaged<LootItem>(ref items);
            }
        }
#endregion
#region Door Profile Storage
        private class DoorProfileStorage : BaseStorage<DoorProfileStorage> {
            public Dictionary<string, DoorProfileEntry> ProfileEntries = new(StringComparer.OrdinalIgnoreCase);
            public bool GetProfileByName(string profileName, out DoorProfileEntry foundEntry) {
                if (string.IsNullOrEmpty(profileName)) {
                    foundEntry = null;
                    return false;
                }
                return ProfileEntries.TryGetValue(profileName, out foundEntry);
            }
            public static DoorProfileEntry DefaultProfile() {
                return new DoorProfileEntry {
                    Health = 1000f, SkinId = 0UL,
                }
                ;
            }
        }
        private class DoorProfileEntry {
            public float Health;
            public ulong SkinId;
        }
#endregion
#region Oxide Hooks
        private void OnServerInitialized() {
            cmd.AddChatCommand("blp", this, nameof(LootProfileCommand));
            cmd.AddChatCommand("bdp", this, nameof(DoorProfileCommand));
            cmd.AddChatCommand("bgp", this, nameof(GuardProfileCommand));
            cmd.AddChatCommand("bse", this, nameof(SpawnEntityCommand));
            cmd.AddChatCommand("bhm", this, nameof(BankManageCommand));
            EntitiesCache.Initialize();
            MonumentCache.Initialize();
            PerformSetupRoutine();
            if (_configData.BlockedCommands.Count > 0) _hooks.Add("OnServerCommand");
            SubscribeToHooks(true);
        }
        private void Init() {
            permission.RegisterPermission(WORKER_PERM, this);
            permission.RegisterPermission(MANAGE_PERM, this);
            _instance = this;
            GuardProfileStorage.LoadData("BankHeist/GuardProfileStorage");
            LootProfileStorage.LoadData("BankHeist/LootProfileStorage");
            DoorProfileStorage.LoadData("BankHeist/DoorProfileStorage");
            BankStorage.LoadData("BankHeist/BankStorage");
            SubscribeToHooks();
        }
        private void Unload() {
            DestroySetupRoutine();
            BankHeistInstance.OnUnload();
            MonumentCache.OnUnload();
            EntitiesCache.OnUnload();
            BankStorage.OnUnload();
            GuardProfileStorage.OnUnload();
            LootProfileStorage.OnUnload();
            DoorProfileStorage.OnUnload();
        }
        private object OnServerCommand(ConsoleSystem.Arg arg) {
            BasePlayer player = arg.Player();
            if (player != null) {
                foreach (string blockedCommand in _configData.BlockedCommands) {
                    if (arg.FullString.EndsWith(blockedCommand, StringComparison.OrdinalIgnoreCase)) {
                        MessagePlayer(player, LangEntry.OnCommandBlocked);
                        return true;
                    }
                }
            }
            return null;
        }
        private void OnEntityTakeDamage(ScientistNPC npc, HitInfo info) {
            if (npc == null || info?.InitiatorPlayer == null || !info.InitiatorPlayer.IsPlayer()) return;
            EntitiesCache.GetBankByEntity(npc.net.ID)?.OnBankAttacked(info.InitiatorPlayer);
        }
        private void OnEntityTakeDamage(Door door, HitInfo info) {
            if (door == null || door.isSecurityDoor || info?.InitiatorPlayer == null || !info.InitiatorPlayer.IsPlayer()) return;
            if (!info.IsMajorityDamage(DamageType.Explosion)) return;
            EntitiesCache.GetBankByEntity(door.net.ID)?.OnBankAttacked(info.InitiatorPlayer);
        }
        private void OnEntityDeath(BasePlayer player, HitInfo info) {
            if (player == null || !player.IsPlayer()) return;
            _players.Remove(player.userID);
        }
        private void OnEntityDeath(ScientistNPC npc, HitInfo info) {
            if (npc == null) return;
            EntitiesCache.GetBankByEntity(npc.net.ID)?.OnEntityDeath(npc, info?.InitiatorPlayer);
        }
        private void OnEntityKill(ScientistNPC npc) {
            if (npc == null) return;
            OnEntityDeath(npc, null);
        }
        private void OnEntityDeath(Door door, HitInfo info) {
            if (door == null) return;
            EntitiesCache.GetBankByEntity(door.net.ID)?.OnEntityDeath(door, info?.InitiatorPlayer);
        }
        private void OnEntityKill(Door door) {
            if (door == null) return;
            OnEntityDeath(door, null);
        }
        private void OnEntityKill(LootContainer container) {
            if (container == null) return;
            EntitiesCache.GetBankByEntity(container.net.ID)?.OnEntityDeath(container);
        }
        private void OnLootEntityEnd(BasePlayer player, LootContainer container) {
            if (container == null) return;
            EntitiesCache.GetBankByEntity(container.net.ID)?.OnLootEntityEnd(player, container);
        }
        private object CanLootEntity(BasePlayer player, LootContainer container) {
            return EntitiesCache.GetBankByEntity(container.net.ID) ?.CanLootEntity(player);
        }
        private object CanHackCrate(BasePlayer player, HackableLockedCrate crate) {
            return EntitiesCache.GetBankByEntity(crate.net.ID) ?.CanHackCrate(player, crate);
        }
        private bool? CanUseLockedEntity(BasePlayer player, CodeLock codeLock) {
            if (codeLock.GetParentEntity() is Door entity) {
                BankHeistInstance instance = EntitiesCache.GetBankByEntity(entity.net.ID);
                if (instance != null && instance.CanUseLockedEntity(player, codeLock)) return true;
                return null;
            }
            return null;
        }
#endregion
#region Bank Heist Instance
        private void PerformSetupRoutine() {
            if (_coroutine != null) return;
            _coroutine = ServerMgr.Instance.StartCoroutine(SpawnBankInstances());
        }
        private void DestroySetupRoutine() {
            if (_coroutine != null) ServerMgr.Instance.StopCoroutine(_coroutine);
            _coroutine = null;
        }
        private IEnumerator SpawnBankInstances() {
            yield return CoroutineEx.waitForSeconds(10f);
            Puts("Initializing banks...");
            Stopwatch stopwatch = Stopwatch.StartNew();
            foreach (BankEntry bankEntry in BankStorage.Data.BankEntries) yield return bankEntry.SpawnBankInstance();
            stopwatch.Stop();
            Puts($"Finished spawning banks: {stopwatch.ElapsedMilliseconds}ms.");
            _coroutine = null;
        }
        private class BankHeistInstance : FacepunchBehaviour {
            public static readonly string DebugText = "<size=24>Bank Information</size>\n----------------------------------\n<size=16>Display Name: {0}\nMonument Parent Name: {1}\nTime Between Resets: {2}\nCrates: {3} | Doors: {4} | Guards: {5}</size>";
            public static List<BankHeistInstance> BankHeistInstances = new();
            private List<SphereEntity> _sphereInstances = new();
            private MapMarkerGenericRadius _markerInstance;
            private IOEntity _alarmInstance;
            public GuardSpawnGroup guardSpawnGroup;
            public LootSpawnGroup lootSpawnGroup;
            public DoorSpawnGroup doorSpawnGroup;
            public string displayName;
            public string monumentName;
            public Vector3 playerDetectionOrigin;
            public float playerDetectionRadius;
            public Vector3 markerOrigin;
            public Color markerReadyColor;
            public Color markerResetColor;
            public Color markerOuterColor;
            public float markerRadius;
            public float markerOpacity;
            public float timeBetweenResets = 3600.0f;
            public float resetTickTime = 10.0f;
            public float resetTimeElapsed;
            public float alarmTime;
            public bool clearAlarm;
            public bool requiresReset;
            public bool lootedEvery;
            public float lastCooldownTime = 60f;
            public float lastAttackedTime;
            public float SecondsSinceAttacked => lastAttackedTime - Time.realtimeSinceStartup;
            public static void OnUnload() {
                if (Rust.Application.isQuitting) return;
                for (int i = BankHeistInstances.Count - 1; i >= 0; i--) BankHeistInstances[i]?.Dispose();
                BankHeistInstances.Clear();
            }
            public static bool FindBankByName(string displayName, out BankHeistInstance heistInstance) {
                heistInstance = BankHeistInstances.Find(x => x.displayName.Equals(displayName, StringComparison.OrdinalIgnoreCase));
                return heistInstance != null;
            }
            public static void CacheHeistInstance(BankHeistInstance bankHeistInstance) => BankHeistInstances.Add(bankHeistInstance);
            public static void RemoveHeistInstance(BankHeistInstance bankHeistInstance) {
                BankHeistInstances.Remove(bankHeistInstance);
                UnityEngine.GameObject.Destroy(bankHeistInstance.gameObject);
            }
#region Unity
            private void OnTriggerEnter(Collider other) {
                BasePlayer player = other?.GetComponentInParent<BasePlayer>();
                if (player == null || !player.userID.IsSteamId()) return;
                _instance._players.Add(player.userID);
                if (_instance._configData.EnableZoneMessages) _instance.MessagePlayer(player, LangEntry.OnEnterZone, displayName);
            }
            private void OnTriggerExit(Collider other) {
                BasePlayer player = other?.GetComponentInParent<BasePlayer>();
                if (player == null || !player.userID.IsSteamId()) return;
                _instance._players.Remove(player.userID);
                if (_instance._configData.EnableZoneMessages) _instance?.MessagePlayer(player, LangEntry.OnLeaveZone, displayName);
            }
#endregion
#region Setup / Destroy
            public IEnumerator Initialize() {
                CreateSpheres();
                CreateMarkers();
                CreateAlarm();
                ResetTimer();
                ResetEvent();
                DebugInfo(DebugMode.Info);
                yield return CoroutineEx.waitForEndOfFrame;
            }
            public void Dispose() {
                StopAllCoroutines();
                CancelInvoke();
                DestroySpheres();
                DestroyMarkers();
                DestroyAlarm();
                DestroySpawnGroups();
                BankHeistInstance.RemoveHeistInstance(this);
            }
#endregion
#region Event Management
            private void ResetTick() {
                bool hasNearbyPlayers = ActiveNearbyPlayers();
                if (!hasNearbyPlayers) resetTimeElapsed += resetTickTime;
                if (resetTimeElapsed <= timeBetweenResets) return;
                if (hasNearbyPlayers) return;
                resetTimeElapsed = 0.0f;
                ResetEvent();
            }
            public void ResetTimer() {
                resetTimeElapsed = 0.0f;
                CancelInvoke(ResetTick);
                InvokeRandomized(ResetTick, UnityEngine.Random.Range(0.0f, 1f), resetTickTime, 0.5f);
            }
            public void ResetEvent() {
                if (!requiresReset) return;
                requiresReset = false;
                lootedEvery = false;
                RemoveNearbySleepers();
                StopAlarm();
                UpdateMarker();
                RefillSpawnGroups();
                _instance?.MessagePlayers(LangEntry.OnBankReset, displayName);
                Interface.Oxide.CallHook("OnBankHeistReset", displayName);
            }
            private bool HasGuardsRemaining() {
                return guardSpawnGroup != null && guardSpawnGroup.spawnInstances.Count > 0;
            }
            private bool ActiveNearbyPlayers() {
                if (BasePlayer.activePlayerList != null && BasePlayer.activePlayerList.Count > 0) {
                    for (int i = BasePlayer.activePlayerList.Count - 1; i >= 0; --i) {
                        BasePlayer player = BasePlayer.activePlayerList[i];
                        if (player.IsValid() && player.IsWithinRadius(playerDetectionOrigin, playerDetectionRadius) && !player.HasP
// ... [Code preview truncated due to length. Full source in attached file] ...

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