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

FREE AutomatedStashTraps : 1.5.4 1.5.4

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Facepunch;
using Network;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Libraries;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Libraries;
using Rust;
using Rust.Workshop;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Oxide.Plugins {
    [Info("Automated Stash Traps", "Dana", "1.5.4")]
    [Description("Spawns fully automated stash traps across the map to catch ESP cheaters.")]
    public class AutomatedStashTraps : RustPlugin {
#region Dependencies
        [PluginReference]
        private readonly Plugin Clans;
#endregion Dependencies
#region Fields
        private static AutomatedStashTraps _instance;
        private static Configuration _config;
        private static Data _data;
        private SpawnPointManager _spawnPointManager;
        private DiscordWebhook _webhook;
        private SkinManager _skinManager;
        private Coroutine _spawnCoroutine;
        private List<BasePlayer> _manualTrapDeployers = new List<BasePlayer>();
        private HashSet<ulong> _revealedOwnedStashes = new HashSet<ulong>();
        private Dictionary<BasePlayer, StorageContainer> _activeLootEditors = new Dictionary<BasePlayer, StorageContainer>();
        private Timer _reportScheduler;
        private Queue<DiscordWebhook.Message> _queuedDiscordReports = new Queue<DiscordWebhook.Message>();
        private const string BLUEPRINT_TEMPLATE = "blueprintbase";
        private const string STASH_PREFAB = "assets/prefabs/deployable/small stash/small_stash_deployed.prefab";
        private const string STORAGE_PREFAB = "assets/prefabs/deployable/large wood storage/box.wooden.large.prefab";
        private const string SLEEPING_BAG_PREFAB = "assets/prefabs/deployable/sleeping bag/sleepingbag_leather_deployed.prefab";
        private Vector3 _lastRevealedStashPosition;
#endregion Fields
#region Configuration
        private class Configuration {
            [JsonProperty("Version")]
            public string Version {
                get;
                set;
            }
            [JsonProperty("Spawn Point")]
            public SpawnPointConfig SpawnPoint {
                get;
                set;
            }
            [JsonProperty("Automated Trap")]
            public AutomatedTrapConfig AutomatedTrap {
                get;
                set;
            }
            [JsonProperty("Violation")]
            public ViolationConfig Violation {
                get;
                set;
            }
            [JsonProperty("Moderation")]
            public ModerationConfig Moderation {
                get;
                set;
            }
            [JsonProperty("Notification")]
            public NotificationConfig Notification {
                get;
                set;
            }
            [JsonProperty("Discord")]
            public DiscordConfig Discord {
                get;
                set;
            }
            [JsonProperty("Stash Loot")]
            public StashLootConfig StashLoot {
                get;
                set;
            }
        }
        private class SpawnPointConfig {
            [JsonProperty("Maximum Attempts To Find Spawn Points")]
            public int MaximumAttemptsToFindSpawnPoints {
                get;
                set;
            }
            [JsonProperty("Safe Area Radius")]
            public float SafeAreaRadius {
                get;
                set;
            }
            [JsonProperty("Entity Detection Radius")]
            public float EntityDetectionRadius {
                get;
                set;
            }
            [JsonProperty("Player Detection Radius")]
            public float PlayerDetectionRadius {
                get;
                set;
            }
        }
        private class AutomatedTrapConfig {
            [JsonProperty("Maximum Traps To Spawn")]
            public int MaximumTrapsToSpawn {
                get;
                set;
            }
            [JsonProperty("Destroy Revealed Trap After Minutes")]
            public int DestroyRevealedTrapAfterMinutes {
                get;
                set;
            }
            [JsonProperty("Replace Revealed Trap")]
            public bool ReplaceRevealedTrap {
                get;
                set;
            }
            [JsonProperty("Dummy Sleeping Bag")]
            public DummySleepingBagConfig DummySleepingBag {
                get;
                set;
            }
        }
        private class DummySleepingBagConfig {
            [JsonProperty("Spawn Along")]
            public bool SpawnAlong {
                get;
                set;
            }
            [JsonProperty("Spawn Proximity To Stash")]
            public float SpawnProximityToStash {
                get;
                set;
            }
            [JsonProperty("Spawn Chance")]
            public int SpawnChance {
                get;
                set;
            }
            [JsonProperty("Randomized Skin Chance")]
            public int RandomizedSkinChance {
                get;
                set;
            }
            [JsonProperty("Randomized Nice Name Chance")]
            public int RandomizedNiceNameChance {
                get;
                set;
            }
        }
        private class ViolationConfig {
            [JsonProperty("Reset On Wipe")]
            public bool ResetOnWipe {
                get;
                set;
            }
            [JsonProperty("Can Teammate Ignore")]
            public bool CanTeammateIgnore {
                get;
                set;
            }
            [JsonProperty("Can Clanmate Ignore")]
            public bool CanClanmateIgnore {
                get;
                set;
            }
        }
        private class ModerationConfig {
            [JsonProperty("Automatic Ban")]
            public bool AutomaticBan {
                get;
                set;
            }
            [JsonProperty("Violations Tolerance")]
            public int ViolationsTolerance {
                get;
                set;
            }
            [JsonProperty("Ban Delay Seconds")]
            public int BanDelaySeconds {
                get;
                set;
            }
            [JsonProperty("Ban Reason")]
            public string BanReason {
                get;
                set;
            }
        }
        private class NotificationConfig {
            [JsonProperty("Prefix")]
            public string Prefix {
                get;
                set;
            }
            [JsonProperty("Enable Console Report")]
            public bool EnableConsoleReport {
                get;
                set;
            }
            [JsonProperty("Stash Report Filter")]
            public int StashReportFilter {
                get;
                set;
            }
        }
        private class DiscordConfig {
            [JsonProperty("Post Into Discord")]
            public bool PostIntoDiscord {
                get;
                set;
            }
            [JsonProperty("Webhook Url")]
            public string WebhookUrl {
                get;
                set;
            }
            [JsonProperty("Report Interval")]
            public float ReportInterval {
                get;
                set;
            }
            [JsonProperty("Message")]
            public string Message {
                get;
                set;
            }
            [JsonProperty("Embed Color")]
            public string EmbedColor {
                get;
                set;
            }
            [JsonProperty("Embed Title")]
            public string EmbedTitle {
                get;
                set;
            }
            [JsonProperty("Embed Footer")]
            public string EmbedFooter {
                get;
                set;
            }
            [JsonProperty("Embed Fields")]
            public List<DiscordWebhook.EmbedField> EmbedFields {
                get;
                set;
            }
            [JsonIgnore]
            private int color;
            [JsonIgnore]
            private bool colorIsValidated;
            public int GetColor() {
                if (!colorIsValidated) {
                    if (!int.TryParse(EmbedColor.TrimStart('#'), NumberStyles.HexNumber, null, out color)) color = 16777215;
                    colorIsValidated = true;
                }
                return color;
            }
        }
        private class StashLootConfig {
            [JsonProperty("Minimum Loot Spawn Slots")]
            public int MinimumLootSpawnSlots {
                get;
                set;
            }
            [JsonProperty("Maximum Loot Spawn Slots")]
            public int MaximumLootSpawnSlots {
                get;
                set;
            }
            [JsonProperty("Spawn Chance As Blueprint")]
            public int SpawnChanceAsBlueprint {
                get;
                set;
            }
            [JsonProperty("Spawn Chance With Skin")]
            public int SpawnChanceWithSkin {
                get;
                set;
            }
            [JsonProperty("Spawn Chance As Damaged")]
            public int SpawnChanceAsDamaged {
                get;
                set;
            }
            [JsonProperty("Minimum Condition Loss")]
            public float MinimumConditionLoss {
                get;
                set;
            }
            [JsonProperty("Maximum Condition Loss")]
            public float MaximumConditionLoss {
                get;
                set;
            }
            [JsonProperty("Spawn Chance As Repaired")]
            public int SpawnChanceAsRepaired {
                get;
                set;
            }
            [JsonProperty("Spawn Chance As Broken")]
            public int SpawnChanceAsBroken {
                get;
                set;
            }
            [JsonProperty("Loot Table")]
            public List<ItemInfo> LootTable {
                get;
                set;
            }
        }
        private class ItemInfo {
            [JsonProperty("Short Name")]
            public string ShortName {
                get;
                set;
            }
            [JsonProperty("Minimum Spawn Amount")]
            public int MinimumSpawnAmount {
                get;
                set;
            }
            [JsonProperty("Maximum Spawn Amount")]
            public int MaximumSpawnAmount {
                get;
                set;
            }
            [JsonIgnore]
            private ItemDefinition itemDefinition;
            [JsonIgnore]
            private bool itemIsValidated;
            // Inspired by WhiteThunder./// <summary>
            /// Returns the item definition associated with this item./// </summary>
            /// <returns> The item definition, or null if the item is not valid.</returns>
            public ItemDefinition GetItemDefinition() {
                if (!itemIsValidated) {
                    ItemDefinition lookupResult = ItemManager.FindItemDefinition(ShortName);
                    if (lookupResult != null) itemDefinition = lookupResult;
                    else return null;
                    itemIsValidated = true;
                }
                return itemDefinition;
            }
            /// <summary>
            /// Determines whether the item can be researched./// </summary>
            /// <returns> True if the item can be researched, false otherwise.</returns>
            public bool CanBeResearched() {
                return itemDefinition.Blueprint == null || !itemDefinition.Blueprint.isResearchable ? false : true;
            }
            /// <summary>
            /// Determines whether the item has skins./// </summary>
            /// <returns> True if the item can be skinned, false otherwise.</returns>
            public bool CanBeSkinned() {
                return !itemDefinition.HasSkins ? false : true;
            }
            /// <summary>
            /// Determines whether the item can be repaired./// </summary>
            /// <returns> True if the item can be repaired, false otherwise.</returns>
            public bool CanBeRepaired() {
                return !itemDefinition.condition.repairable ? false : true;
                // !item.hasCondition
            }
        }
        private Configuration GetDefaultConfig() {
            return new Configuration {
                Version = Version.ToString(), SpawnPoint = new SpawnPointConfig {
                    MaximumAttemptsToFindSpawnPoints = 1500, SafeAreaRadius = 3f, EntityDetectionRadius = 25f, PlayerDetectionRadius = 25f
                }
                , AutomatedTrap = new AutomatedTrapConfig {
                    MaximumTrapsToSpawn = 50, DestroyRevealedTrapAfterMinutes = 2, ReplaceRevealedTrap = true, DummySleepingBag = new DummySleepingBagConfig {
                        SpawnAlong = false, SpawnProximityToStash = 0.90f, SpawnChance = 50, RandomizedSkinChance = 40, RandomizedNiceNameChance = 60
                    }
                }
                , Violation = new ViolationConfig {
                    ResetOnWipe = true, CanTeammateIgnore = false, CanClanmateIgnore = false
                }
                , Moderation = new ModerationConfig {
                    AutomaticBan = false, ViolationsTolerance = 3, BanDelaySeconds = 60, BanReason = "Cheat Detected!"
                }
                , Notification = new NotificationConfig {
                    Prefix = "<color=#F2C94C>Automated Stash Trap</color>:", EnableConsoleReport = true, StashReportFilter = 2
                }
                , Discord = new DiscordConfig {
                    PostIntoDiscord = false, WebhookUrl = string.Empty, ReportInterval = 60f, Message = "Cheater, cheater, pumpkin eater! Looks like someone's been caught breaking the rules!", EmbedTitle = "A cheater has been spotted", EmbedColor = "#FFFFFF", EmbedFooter = string.Empty, EmbedFields = new List<DiscordWebhook.EmbedField>() {
                        new DiscordWebhook.EmbedField {
                            Name = "Player Name", Value = "$Player.Name", Inline = true
                        }
                        , new DiscordWebhook.EmbedField {
                            Name = "Id", Value = "$Player.Id", Inline = true
                        }
                        , new DiscordWebhook.EmbedField {
                            Name = "Violations Count", Value = "$Player.Violations", Inline = true
                        }
                        , new DiscordWebhook.EmbedField {
                            Name = "Revealed Stash Type", Value = "$Stash.Type", Inline = true
                        }
                        , new DiscordWebhook.EmbedField {
                            Name = "Stash Id", Value = "$Stash.Id", Inline = true
                        }
                        , new DiscordWebhook.EmbedField {
                            Name = "Grid", Value = "$Stash.Position.Grid", Inline = true
                        }
                        , new DiscordWebhook.EmbedField {
                            Name = "Reveal Method", Value = "$Stash.Reveal.Method", Inline = false
                        }
                        , new DiscordWebhook.EmbedField {
                            Name = "Stash Owner Name", Value = "$Stash.Owner.Name", Inline = true
                        }
                        , new DiscordWebhook.EmbedField {
                            Name = "Stash Owner Id", Value = "$Stash.Owner.Id", Inline = true
                        }
                        , new DiscordWebhook.EmbedField {
                            Name = "Team Info", Value = "$Player.Team", Inline = false
                        }
                        , new DiscordWebhook.EmbedField {
                            Name = "Player Connection Time", Value = "$Player.Connection.Time", Inline = false
                        }
                        , new DiscordWebhook.EmbedField {
                            Name = "Server", Value = "$Server.Name $Server.Address", Inline = false
                        }
                        ,
                    }
                }
                , StashLoot = new StashLootConfig {
                    MinimumLootSpawnSlots = 1, MaximumLootSpawnSlots = 6, SpawnChanceAsBlueprint = 10, SpawnChanceWithSkin = 50, SpawnChanceAsDamaged = 30, MinimumConditionLoss = 5f, MaximumConditionLoss = 95f, SpawnChanceAsRepaired = 15, SpawnChanceAsBroken = 5, LootTable = new List<ItemInfo>() {
                        new ItemInfo {
                            ShortName = "scrap", MinimumSpawnAmount = 25, MaximumSpawnAmount = 125,
                        }
                        , new ItemInfo {
                            ShortName = "metal.refined", MinimumSpawnAmount = 15, MaximumSpawnAmount = 40,
                        }
                        , new ItemInfo {
                            ShortName = "cloth", MinimumSpawnAmount = 60, MaximumSpawnAmount = 200,
                        }
                        , new ItemInfo {
                            ShortName = "cctv.camera", MinimumSpawnAmount = 1, MaximumSpawnAmount = 2,
                        }
                        , new ItemInfo {
                            ShortName = "riflebody", MinimumSpawnAmount = 1, MaximumSpawnAmount = 3,
                        }
                        , new ItemInfo {
                            ShortName = "techparts", MinimumSpawnAmount = 1, MaximumSpawnAmount = 6,
                        }
                    }
                }
            }
            ;
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            _config = Config.ReadObject<Configuration>();
            if (string.Compare(_config.Version, Version.ToString()) < 0) UpdateConfig();
            ValidateConfigValues();
            SaveConfig();
        }
        protected override void LoadDefaultConfig() {
            _config = GetDefaultConfig();
        }
        protected override void SaveConfig() {
            Config.WriteObject(_config, true);
        }
        private void UpdateConfig() {
            PrintWarning("Detected changes in configuration! Updating...");
            Configuration defaultConfig = GetDefaultConfig();
            if (string.Compare(_config.Version, "1.0.0") < 0) _config = defaultConfig;
            if (string.Compare(_config.Version, "1.1.0") < 0) {
                _config.Violation = defaultConfig.Violation;
                _config.Moderation = defaultConfig.Moderation;
            }
            if (string.Compare(_config.Version, "1.3.0") < 0) {
                _config.Discord.ReportInterval = defaultConfig.Discord.ReportInterval;
            }
            if (string.Compare(_config.Version, "1.4.0") < 0) {
                _config.Notification = defaultConfig.Notification;
                _config.AutomatedTrap.DummySleepingBag.SpawnProximityToStash = defaultConfig.AutomatedTrap.DummySleepingBag.SpawnProximityToStash;
            }
            if (string.Compare(_config.Version, "1.5.0") < 0) {
                _config.Notification.StashReportFilter = defaultConfig.Notification.StashReportFilter;
            }
            PrintWarning("Configuration update complete! Updated from version " + _config.Version + " to " + Version.ToString());
            _config.Version = Version.ToString();
        }
        private void ValidateConfigValues() {
            PrintWarning("Validating configuration values...");
            if (_config.AutomatedTrap.DestroyRevealedTrapAfterMinutes <= 0) {
                PrintError("Invalid trap removal time value.To avoid potential entity leaks, this value must be greater than 0.Default value of 5 will be applied.");
                _config.AutomatedTrap.DestroyRevealedTrapAfterMinutes = 5;
            }
            if (_config.AutomatedTrap.DummySleepingBag.SpawnProximityToStash <= 0.0f || _config.AutomatedTrap.DummySleepingBag.SpawnProximityToStash > 1.0f) {
                PrintError("Invalid sleeping bag spawn proximity.The value must be greater than 0.0 and less than or equal to 1.0.Default value of 0.9 will be applied.");
                _config.AutomatedTrap.DummySleepingBag.SpawnProximityToStash = 0.90f;
            }
            if (_config.Notification.StashReportFilter < 0 || _config.Notification.StashReportFilter > 2) {
                PrintError("Invalid stash report filter value.The value must be 0, 1, or 2.Default value of 2 will be applied.");
                _config.Notification.StashReportFilter = 2;
            }
            if (_config.Discord.PostIntoDiscord) {
                if (string.IsNullOrWhiteSpace(_config.Discord.WebhookUrl)) {
                    PrintError("Invalid webhook url provided.Please provide a valid webhook url to post into Discord.");
                    _config.Discord.PostIntoDiscord = false;
                }
                if (string.IsNullOrWhiteSpace(_config.Discord.EmbedColor) || !_config.Discord.EmbedColor.StartsWith("#")) {
                    PrintError("Invalid color provided.The color must be a valid hex color code.Default color of #FFFFFF will be applied.");
                    _config.Discord.EmbedColor = "#FFFFFF";
                }
            }
            if (_config.StashLoot.MinimumLootSpawnSlots < 1) {
                PrintError("Invalid minimum loot spawn slots value.Default value of 1 will be applied.");
                _config.StashLoot.MinimumLootSpawnSlots = 1;
            }
            if (_config.StashLoot.MaximumLootSpawnSlots > 6) {
                PrintError("Invalid maximum loot spawn slots value.Default value of 6 will be applied.");
                _config.StashLoot.MaximumLootSpawnSlots = 6;
            }
            List<ItemInfo> invalidItems = _config.StashLoot.LootTable.Where(item => item.GetItemDefinition() == null).ToList();
            foreach (ItemInfo invalidItem in invalidItems) {
                _config.StashLoot.LootTable.Remove(invalidItem);
                PrintError("Invalid item '" + invalidItem.ShortName + "' removed from the loot table.");
            }
            foreach (ItemInfo item in _config.StashLoot.LootTable) {
                if (item.MinimumSpawnAmount <= 0) {
                    PrintError("Invalid minimum spawn amount for item '" + item.ShortName + "'.Default value of 1 will be applied.");
                    item.MinimumSpawnAmount = 1;
                }
                if (item.MaximumSpawnAmount < item.MinimumSpawnAmount) {
                    PrintError("Invalid maximum spawn amount for item '" + item.ShortName + "'.Default value of " + item.MinimumSpawnAmount + " will be applied.");
                    item.MaximumSpawnAmount = item.MinimumSpawnAmount;
                }
            }
            PrintWarning("Configuration validation complete!");
        }
#endregion
#region Data
        private class Data {
            [JsonProperty("Violations")]
            public Dictionary<ulong, int> Violations {
                get;
                set;
            }
            = new Dictionary<ulong, int>();
            [JsonProperty("Automated Traps")]
            public Dictionary<ulong, AutomatedTrapData> AutomatedTraps {
                get;
                set;
            }
            = new Dictionary<ulong, AutomatedTrapData>();
            public static Data Load() {
                return Interface.Oxide.DataFileSystem.ReadObject<Data>(_instance.Name) ?? new Data();
            }
            public Data Save() {
                Interface.Oxide.DataFileSystem.WriteObject(_instance.Name, this);
                return this;
            }
            public static Data Clear() {
                return new Data().Save();
            }
            public void RemovePlayerData(BasePlayer player) {
                if (Violations.ContainsKey(player.userID)) Violations.Remove(player.userID);
            }
            public void CreateOrUpdatePlayerData(BasePlayer player) {
                int revealedTraps;
                Violations.TryGetValue(player.userID, out revealedTraps);
                Violations[player.userID] = revealedTraps + 1;
            }
            public int GetPlayerRevealedTrapsCount(BasePlayer player) {
                int revealedTraps;
                return Violations.TryGetValue(player.userID, out revealedTraps) ? revealedTraps : 0;
            }
            public void CreateTrapData(StashContainer stash, SleepingBag sleepingBag = null) {
                AutomatedTraps[stash.net.ID.Value] = new AutomatedTrapData {
                    DummyStash = new DummyStashData {
                        Hidden = true, Id = stash.net.ID.Value, Position = stash.ServerPosition
                    }
                }
                ;
                if (sleepingBag != null) AutomatedTraps[stash.net.ID.Value].DummySleepingBag = new DummySleepingBagData {
                    Id = sleepingBag.net.ID.Value, NiceName = sleepingBag.niceName, SkinId = sleepingBag.skinID, Position = sleepingBag.ServerPosition
                }
                ;
            }
            public AutomatedTrapData GetTrapData(ulong trapId) {
                AutomatedTrapData trapData;
                return AutomatedTraps.TryGetValue(trapId, out trapData) ? trapData : null;
            }
            public void UpdateTrapData(AutomatedTrapData trap) {
                trap.DummyStash.Hidden = false;
            }
        }
        private class AutomatedTrapData {
            [JsonProperty("Dummy Stash")]
            public DummyStashData DummyStash {
                get;
                set;
            }
            [JsonProperty("Dummy Sleeping Bag")]
            public DummySleepingBagData DummySleepingBag {
                get;
                set;
            }
        }
        private class DummyStashData {
            [JsonProperty("Hidden")]
            public bool Hidden {
                get;
                set;
            }
            [JsonProperty("Id")]
            public ulong Id {
                get;
                set;
            }
            [JsonProperty("Position")]
            public Vector3 Position {
                get;
                set;
            }
        }
        private class DummySleepingBagData {
            [JsonProperty("Id")]
            public ulong Id {
                get;
                set;
            }
            [JsonProperty("Nice Name")]
            public string NiceName {
                get;
                set;
            }
            [JsonProperty("Skin Id")]
            public ulong SkinId {
                get;
                set;
            }
            [JsonProperty("Position")]
            public Vector3 Position {
                get;
                set;
            }
        }
#endregion
#region Oxide Hooks
        /// <summary>
        /// Hook: Called when a plugin is being initialized./// </summary>
        private void Init() {
            _instance = this;
            _skinManager = new SkinManager();
            _webhook = new DiscordWebhook();
            _spawnPointManager = new SpawnPointManager();
            _data = Data.Load();
            PermissionUtils.Register();
        }
        /// <summary>
        /// Hook: Called after server startup is complete and awaits connections or when a plugin is hotloaded while the server is running./// </summary>
        private void OnServerInitialized() {
            StartSpawnCoroutine();
        }
        /// <summary>
        /// Hook: Called when a plugin is being unloaded./// </summary>
        private void Unload() {
            CleanupTraps();
            StopSpawnCoroutine();
            _spawnPointManager.ClearAvailableSpawnPoints();
            _lastRevealedStashPosition = Vector3.zero;
            _reportScheduler?.Destroy();
            _instance = null;
            _config = null;
            _data = null;
        }
        /// <summary>
        /// Hook: Called when a new save file is created./// </summary>
        private void OnNewSave() {
            if (_config.Violation.ResetOnWipe) Data.Clear();
        }
        /// <summary>
        /// Hook: Called when any entity is built or deployed./// </summary>
        /// <param name="planner"> The building planner held by the player.</param>
        /// <param name="gameObject"> Contains information about the built entity.</param>
        private void OnEntityBuilt(Planner planner, GameObject gameObject) {
            StashContainer stash = gameObject?.ToBaseEntity() as StashContainer;
            if (!stash) return;
            BasePlayer deployingPlayer = planner?.GetOwnerPlayer();
            if (!deployingPlayer) return;
            if (!_manualTrapDeployers.Contains(deployingPlayer)) return;
            PopulateLoot(stash);
            stash.SetHidden(true);
            _manualTrapDeployers.Remove(deployingPlayer);
            ReplyToPlayer(deployingPlayer, GetLang(Lang.TRAP_SETUP, deployingPlayer.UserIDString));
            Draw.Sphere(deployingPlayer, 60f, ParseColor("#BDBDBD", Color.white), stash.transform.position, 0.5f);
            Draw.Text(deployingPlayer, 60f, ParseColor("#F2C94C", Color.white), stash.transform.position + new Vector3(0, 0.7f, 0), $"<size=30>{stash.net.ID}</size>");
        }
        /// <summary>
        /// Hook: Called when the player stops looting./// </summary>
        /// <param name="inventory"> The inventory that the player was looting.</param>
        private void OnPlayerLootEnd(PlayerLoot inventory) {
            CloseLootEditor(inventory);
        }
        /// <summary>
        /// Hook: Called when an entity is destroyed./// </summary>
        /// <param name="stash"> The stash container that has been destroyed.</param>
        private void OnEntityKill(StashContainer stash) {
            if (stash.IsValid()) HandleDestroyedStash(stash);
        }
        /// <summary>
        /// Hook: Called when a player reveals a hidden stash./// </summary>
        /// <param name="stash"> The stash that was revealed.</param>
        /// <param name="player"> The player who revealed the stash.</param>
        private void OnStashExposed(StashContainer stash, BasePlayer player) {
            if (PermissionUtils.Verify(player, PermissionUtils.IGNORE)) return;
            OnStashTriggered(stash, player, false);
        }
        /// <summary>
        /// Hook: Called when a player hides a stash./// </summary>
        /// <param name="stash"> The stash that was hidden.</param>
        /// <param name="player"> The player who buried the stash.</param>
        private void OnStashHidden(StashContainer stash, BasePlayer player) {
            if (PlayerIsStashOwner(stash, player)) return;
            else if (!PlayerExistsInOwnerTeam(stash.OwnerID, player)) _revealedOwnedStashes.Add(stash.net.ID.Value);
        }
#endregion Oxide Hooks
#region Spawn Coroutine
        /// <summary>
        /// Starts a coroutine that gradually spawns automated traps over time./// </summary>
        private void StartSpawnCoroutine() {
            // Hold a reference to the coroutine that is currently running._spawnCoroutine = ServerMgr.Instance.StartCoroutine(SpawnTraps());
        }
        /// <summary>
        /// Stops the periodic spawning of automated traps if it is currently running./// </summary>
        private void StopSpawnCoroutine() {
            // Proceed if the coroutine is currently running.if (!_spawnCoroutine.IsUnityNull())
            {
                // Stop the execution of the coroutine and release it to be garbage collected.ServerMgr.Instance.StopCoroutine(_spawnCoroutine);
                _spawnCoroutine = null;
            }
        }
#endregion Spawn Coroutine
#region Trap Creation
        /// <summary>
        /// Spawns a specified number of automated traps, consisting of a stash and, optionally, a dummy sleeping bag./// </summary>
        /// <returns> The number of traps that were spawned.</returns>
        private IEnumerator SpawnTraps() {
            // Keep track of the number of traps that have been spawned.int spawnedTraps = 0;
            // Calculate the number of traps that need to be spawned.int trapsToSpawn = _config.AutomatedTrap.MaximumTrapsToSpawn - _data.AutomatedTraps.Where(trapData => trapData.Value.DummyStash.Hidden).Count();
            // If there are no traps to spawn, exit early.if (trapsToSpawn <= 0)
            yield break;
            // Determine the wait duration for the coroutine based on the current frame rate limit.WaitForSeconds waitDuration = ConVar.FPS.limit > 80 ? CoroutineEx.waitForSeconds(0.01f) : null;
            // If there are not enough available spawn points, generate more until there are enough.if (_spawnPointManager.AvailableSpawnPointsCount < trapsToSpawn)
            {
                int spawnPointsToGenerate = trapsToSpawn - _spawnPointManager.AvailableSpawnPointsCount;
                yield return ServerMgr.Instance.StartCoroutine(_spawnPointManager.GenerateSpawnPoints(spawnPointsToGenerate));
            }
            // Begin spawning traps until the required number has been reached.for (int i = 0; i < trapsToSpawn; i++)
            {
                // Get a random spawn point.Tuple<Vector3, Quaternion> spawnPoint = _spawnPointManager.GetRandomSpawnPoint();
                // Create a stash container entity at the spawn point and populate it with loot.StashContainer stash = CreateStashEntity(STASH_PREFAB, spawnPoint.Item1, spawnPoint.Item2);
                PopulateLoot(stash);
                // Initialize a sleeping bag entity, which may be spawned if the configuration allows it.SleepingBag sleepingBag = null;
                if (_config.AutomatedTrap.DummySleepingBag.SpawnAlong && ChanceSucceeded(_config.AutomatedTrap.DummySleepingBag.SpawnChance)) {
                    // Find a nearby spawn point and create a sleeping bag at it.Tuple<Vector3, Quaternion> nearbySpawnPoint = _spawnPointManager.FindChildSpawnPoint(spawnPoint.Item1);
                    sleepingBag = CreateSleepingBagEntity(SLEEPING_BAG_PREFAB, nearbySpawnPoint.Item1, nearbySpawnPoint.Item2);
                }
                _data.CreateTrapData(stash, sleepingBag);
                spawnedTraps++;
                // Wait for a set duration to prevent overloading the server with spawning actions.yield return waitDuration;
            }
            // Output the total number of spawned traps to the console.Puts("Spawned " + spawnedTraps + " traps.");
            // Save the trap _data and set the coroutine to null to be garbage collected._data.Save();
        }
        /// <summary>
        /// Creates a stash entity from the specified prefab at the given position and rotation./// </summary>
        /// <param name="prefabPath"> The path to the prefab to use for the stash entity.</param>
        /// <param name="position"> The position to spawn the stash entity at.</param>
        /// <param name="rotation"> The rotation to spawn the stash entity with.</param>
        /// <returns> The created stash entity, or null if the entity could not be created.</returns>
        private StashContainer CreateStashEntity(string prefabPath, Vector3 position, Quaternion rotation) {
            // Create the entity from the specified prefab.BaseEntity entity = GameManager.server.CreateEntity(prefabPath, position, rotation);
            // Don't proceed if the entity could not be created.if (entity == null)
            return null;
            // Convert the entity to a StashContainer.StashContainer stash = entity as StashContainer;
            if (stash == null) {
                // Destroy the entity if it could not be converted.UnityEngine.Object.Destroy(entity);
                return null;
            }
            // Initialize the stash by spawning and hiding it underground.stash.Spawn();
            stash.SetHidden(true);
            // Cancel the decay invoke, so the stash does not decay over time.stash.CancelInvoke(stash.Decay);
            return stash;
        }
        /// <summary>
        /// Creates a sleeping bag entity from the specified prefab at the given position and rotation./// </summary>
        /// <param name="prefabPath"> The path to the prefab to use for the sleeping bag entity.</param>
        /// <param name="position"> The position to spawn the sleeping bag entity at.</param>
        /// <param name="rotation"> The rotation to spawn the sleeping bag entity with.</param>
        /// <returns> The created sleeping bag entity, or null if the entity could not be created.</returns>
        private SleepingBag CreateSleepingBagEntity(string prefabPath, Vector3 position, Quaternion rotation) {
            // Create the entity from the specified prefab.BaseEntity entity = GameManager.server.CreateEntity(prefabPath, position, rotation);
            // Don't proceed if the entity could not be created.if (entity == null)
            return null;
            // Convert the entity to a SleepingBag.SleepingBag sleepingBag = entity as SleepingBag;
            if (sleepingBag == null) {
                // Destroy the entity if it could not be converted.UnityEngine.Object.Destroy(entity);
                return null;
            }
            UnityEngine.Object.DestroyImmediate(sleepingBag.GetComponent<DestroyOnGroundMissing>());
            UnityEngine.Object.DestroyImmediate(sleepingBag.GetComponent<GroundWatch>());
            // Set a random skin for the sleeping bag.if (_config.AutomatedTrap.DummySleepingBag.RandomizedSkinChance > 0 && ChanceSucceeded(_config.AutomatedTrap.DummySleepingBag.RandomizedSkinChance))
            sleepingBag.skinID = _skinManager.GetSkinsForItem(ItemManager.FindItemDefinition("sleepingbag")).GetRandom();
            // Set a random nice name for the sleeping bag.if (_config.AutomatedTrap.DummySleepingBag.RandomizedNiceNameChance > 0 && ChanceSucceeded(_config.AutomatedTrap.DummySleepingBag.RandomizedNiceNameChance))
            sleepingBag.niceName = RandomUsernames.Get(Random.Range(0, 5000));
            // Spawn the sleeping bag.sleepingBag.Spawn();
            return sleepingBag;
        }
        private void PopulateLoot(StashContainer stash) {
            List<ItemInfo> itemsToSpawn = new List<ItemInfo>(_config.StashLoot.LootTable);
            int lootSpawnSlots = Random.Range(_config.StashLoot.MinimumLootSpawnSlots, _config.StashLoot.MaximumLootSpawnSlots);
            if (lootSpawnSlots > itemsToSpawn.Count) lootSpawnSlots = itemsToSpawn.Count;
            stash.inventory.Clear();
            for (int i = 0; i < lootSpawnSlots; i++) {
                Item item;
                ItemInfo randomItem = itemsToSpawn.GetRandom();
                ItemDefinition itemDefinition = randomItem.GetItemDefinition();
                if (itemDefinition == null) continue;
                if (_config.StashLoot.SpawnChanceAsBlueprint > 0 && randomItem.CanBeResearched() && ChanceSucceeded(_config.StashLoot.SpawnChanceAsBlueprint)) {
                    item = ItemManager.CreateByName(BLUEPRINT_TEMPLATE);
                    item.blueprintTarget = itemDefinition.itemid;
                }
                else {
                    int spawnAmount = Random.Range(randomItem.MinimumSpawnAmount, randomItem.MaximumSpawnAmount + 1);
                    ulong skin = 0;
                    if (_config.StashLoot.SpawnChanceWithSkin > 0 && randomItem.CanBeSkinned() && ChanceSucceeded(_config.StashLoot.SpawnChanceWithSkin)) skin = _instance._skinManager.GetSkinsForItem(itemDefinition).GetRandom();
                    item = ItemManager.CreateByName(randomItem.ShortName, spawnAmount, skin);
                    if (_config.StashLoot.SpawnChanceAsDamaged > 0 && randomItem.CanBeRepaired()) RandomizeItemCondition(item);
                }
                // Remove the item if it wasn't added successfully to avoid any potential entity leak.if (!item.MoveToContainer(stash.inventory))
                item.Remove();
                item.MarkDirty();
                itemsToSpawn.Remove(randomItem);
            }
            Pool.FreeList(ref itemsToSpawn);
        }
        private void RandomizeItemCondition(Item item) {
            if (ChanceSucceeded(_config.StashLoot.SpawnChanceAsDamaged)) {
                float conditionLoss = Random.Range(_config.StashLoot.MinimumConditionLoss, _config.StashLoot.MaximumConditionLoss);
                item.conditionNormalized = conditionLoss / 100;
            }
            if (ChanceSucceeded(_config.StashLoot.SpawnChanceAsRepaired)) {
                float repairAmount = Random.Range(1f, 0.8f);
                item.DoRepair(repairAmount);
            }
            else if (ChanceSucceeded(_config.StashLoot.SpawnChanceAsBroken)) {
                item.condition = 0f;
            }
        }
#endregion Trap Creation
#region Trap Removal
        /// <summary>
        /// Removes all automated traps from the world and their associated entities./// </summary>
        /// <returns> The number of removed traps.</returns>
        private void CleanupTraps() {
            // Keep track of the number of removed traps.int removedTraps = 0;
            // Process all traps one by one.foreach (ulong trapId in _data.AutomatedTraps.Keys)
            {
                // Retrieve the _data for the current trap.AutomatedTrapData trap = _data.GetTrapData(trapId);
                // Skip the trap if its _data cannot be found and move on to the next one.if (trap == null)
                continue;
                // Find the stash for the current trap and kill it if found.StashContainer stash = FindEntityById(trap.DummyStash.Id) as StashContainer;
                stash?.Kill();
                // Find the dummy sleeping bag associated with the trap and kill it if found.if (trap.DummySleepingBag != null)
                {
                    SleepingBag sleepingBag = FindEntityById(trap.DummySleepingBag.Id) as SleepingBag;
                    sleepingBag?.Kill();
                }
                // Increment the number of successfully removed traps.removedTraps++;
            }
            Puts("Cleaned up " + removedTraps + " traps.");
            _data.AutomatedTraps.Clear();
            _data.Save();
        }
        /// <summary>
        /// Schedules the destruction of an automated trap and, optionally, replaces it with a new one./// </summary>
        /// <param name="trap"> The AutomatedTrapData object containing information about the trap to be destroyed and replaced.</param>
        private void TryDestroyAndReplaceTrap(AutomatedTrapData trap) {
            // Schedule the trap for destruction after the specified time interval.timer.Once(_config.AutomatedTrap.DestroyRevealedTrapAfterMinutes * 60, () =>
            {
                // Find the dummy stash associated with the trap and destroy it if found.StashContainer stash = FindEntityById(trap.DummyStash.Id) as StashContainer;
                stash?.Kill();
                // Find the dummy sleeping bag associated with the trap and destroy it if found.if (trap.DummySleepingBag != null)
                {
                    SleepingBag sleepingBag = FindEntityById(trap.DummySleepingBag.Id) as SleepingBag;
                    sleepingBag?.Kill();
                }
                // Remove the trap from the AutomatedTraps list._data.AutomatedTraps.Remove(trap.DummyStash.Id);
                // If specified in the _config, spawn a new automated trap after the old one has been destroyed.if (_config.AutomatedTrap.ReplaceRevealedTrap)
                StartSpawnCoroutine();
            }
            );
        }
#endregion Trap Removal
#region Trap Trigger
        private void OnStashTriggered(StashContainer stash, BasePlayer player, bool stashWasDestroyed) {
            AutomatedTrapData trap = _data.GetTrapData(stash.net.ID.Value);
            if (trap != null) {
                if (_config.Notification.StashReportFilter != 0 && _config.Notification.StashReportFilter != 2) return;
                if (!trap.DummyStash.Hidden) return;
                _data.UpdateTrapData(trap);
                TryDestroyAndReplaceTrap(trap);
            }
            else if (StashIsOwned(stash)) {
                if (_config.Notification.StashReportFilter != 1 && _config.Notification.StashReportFilter != 2) return;
                if (_revealedOwnedStashes.Contains(stash.net.ID.Value)) return;
                if (PlayerIsStashOwner(stash, player)) return;
                if (_config.Violation.CanTeammateIgnore && PlayerExistsInOwnerTeam(stash.OwnerID, player)) return;
                if (_config.Violation.CanClanmateIgnore && PlayerExistsInOwnerClan(stash.OwnerID, player)) return;
                if (!stashWasDestroyed) _revealedOwnedStashes.Add(stash.net.ID.Value);
            }
            _lastRevealedStashPosition = stash.ServerPosition;
            _data.CreateOrUpdatePlayerData(player);
            _data.Save();
            int violations = _data.GetPlayerRevealedTrapsCount(player);
            if (_config.Moderation.AutomaticBan && violations >= _config.Moderation.ViolationsTolerance) IssueBan(player);
            if (_config.Notification.EnableConsoleReport) {
                string report = ConstructConsoleReport(stash, player);
                Puts(report);
            }
            if (_config.Discord.PostIntoDiscord) {
                DiscordWebhook.Message message = ConstructDiscordReport(stash, player, stashWasDestroyed);
                _queuedDiscordReports.Enqueue(message);
                if (_reportScheduler == null) {
                    _reportScheduler = timer.Once(_config.Discord.ReportInterval, () => {
                        PushQueuedDiscordReports();
                        _reportScheduler = null;
                    }
                    );
                }
            }
            foreach (BasePlayer admin in BasePlayer.activePlayerList.Where(p => PermissionUtils.Verify(p))) {
                ReplyToPlayer(admin, GetLang(Lang.TRAP_REVEAL, admin.UserIDString), player.displayName, GetGrid(stash.ServerPosition));
                Draw.Sphere(admin, 60f, Color.black, _lastRevealedStashPosition, 0.5f);
                Draw.Arrow(admin, 60f, Color.black, _lastRevealedStashPosition + new Vector3(0, 390f, 0), _lastRevealedStashPosition, 0.50f);
                Draw.Text(admin, 60f, ParseColor("#F2C94C", Color.white), _lastRevealedStashPosition + new Vector3(0, 390.1f, 0), $"<size=25>{player.displayName}</size>");
            }
        }
        private string ConstructConsoleReport(StashContainer stash, BasePlayer player) {
            StringBuilder reportBuilder = new StringBuilder();
  
// ... [Code preview truncated due to length. Full source in attached file] ...

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