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

FREE DungeonEvents : 3.7.0 3.7.0

Нет прав для скачивания
C#:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Facepunch;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust;
using UnityEngine;
using Random = UnityEngine.Random;

namespace Oxide.Plugins
{
    [Info("Dungeon Events", "Marte6", "3.7.0")]
    [Description("Create dungeons populated with NPCs, turrets and loot containers.")]
    public class DungeonEvents : RustPlugin
    {
        #region Fields
        [PluginReference]
        private Plugin NpcSpawn,
            Friends,
            Economics,
            ServerRewards,
            Notify,
            NightVision,
            ZoneManager,
            Duelist,
            RaidableBases,
            AbandonedBases,
            RestoreUponDeath,
            SkillTree;
        private static DungeonEvents _instance;
        private Configuration _config;
        private List<ActiveDungeon> _activeDungeons = new List<ActiveDungeon>();
        private List<BasePlayer> _playersBuying = new List<BasePlayer>();
        private List<BasePlayer> _wasInDungeonPlayers = new List<BasePlayer>();
        private Dictionary<ulong, Dictionary<string, DateTime>> _buyCooldowns = new Dictionary<ulong, Dictionary<string, DateTime>>();
        private List<DungeonMarker> _activeDungeonMarkers = new List<DungeonMarker>();
        private Queue<DungeonRequest> _dungeonQueue = new Queue<DungeonRequest>();
        private Queue<DungeonRequest> _dungeonFailedAutoSpawnQueue = new Queue<DungeonRequest>();
        private Queue<DungeonRequest> _dungeonFailedBuyQueue = new Queue<DungeonRequest>();
        private Timer _dungeonTimer;
        private bool isCreatingDungeon = false;
        private const float TimeTimers = 10f;
        private const string PermissionAdmin = "dungeonevents.admin";
        private const string PermissionBuy = "dungeonevents.buy";
        private const string PermissionEnter = "dungeonevents.enter";
        private const ulong OwnerID = 10203040505;
        private const string UiEventPanel = "yFifW5s1zAY09h5cU0qeIQUNV6GGwevG";
        private const string UiMainPanel = "5cU06GGweeIQ09hyFifW5qvGVsUNAY1z";
        private const string UiCommandClose = "lDM82GJH3biLcI95ic8zzteteOeQx77h";
        private Dictionary<DungeonTierConfig, TierInfo> _tierInfoMap = new Dictionary<DungeonTierConfig, TierInfo>();
        private DateTime _lastAutoSpawnTime = DateTime.MinValue;
        private WaitForSeconds SmallDelay = new WaitForSeconds(0.15f);
        private WaitForSeconds BigDelay = new WaitForSeconds(0.50f);
        private Coroutine _startupRoutine;
        private const string WallPrefab = "assets/prefabs/building core/wall/wall.prefab";
        private const string FoundationPrefab = "assets/prefabs/building core/foundation/foundation.prefab";
        private const string CeilingPrefab = "assets/prefabs/building core/floor/floor.prefab";
        private const string TurretPrefab = "assets/prefabs/npc/autoturret/autoturret_deployed.prefab";
        private const string LightPrefab = "assets/bundled/prefabs/modding/cinematic/cinelights/cinelight_point_red.prefab";
        private const string PortalPrefab = "assets/prefabs/missions/portal/halloweenportalexit.prefab";
        private const string WallFramePrefab = "assets/prefabs/building core/wall.frame/wall.frame.prefab";
        private const string DoorPrefab = "assets/prefabs/building/wall.frame.garagedoor/wall.frame.garagedoor.prefab";
        private readonly List<ActiveDungeon> _activeRooms = new List<ActiveDungeon>();
        private readonly Dictionary<Vector3, ZoneInfo> _blockedZones = new Dictionary<Vector3, ZoneInfo>();
        private readonly Vector3 _wallOffset = new Vector3(-1.5f, 0, -1.5f);
        private static readonly Vector3 CeilingLightOffset = new Vector3(-1.5f, 0, -1.5f);
        private static readonly List<string> RockKeywords = new List<string> { "rock", "formation", "junk", "cliff", "invisible" };
        private int _gridSize = 5;
        private const int SubCells = 2;
        private const int MinimumActiveCells = 13;
        private const int MaxGenerationAttempts = 1000;
        private const float CellSpacing = 6f;
        private const float SubCellSpacing = 3f;
        private const float WallRotationOffset = 90f;
        private const float CeilingHeight = 3f;
        private const float CorridorLength = 12f;
        private const bool SpawnTurrets = false;
        private const bool PlaceCeiling = true;
        private const bool PlaceLights = true;
        private uint _randomSeed;
        #endregion

        #region Hooks
        void Init()
        {
            _instance = this;
            permission.RegisterPermission(PermissionEnter, this);
            permission.RegisterPermission(PermissionAdmin, this);
            permission.RegisterPermission(PermissionBuy, this);
        }

        void OnServerInitialized()
        {
            float smallDelaySec = Mathf.Clamp(_config.SmallDelay, 0.15f, 5f);
            float bigDelaySec = Mathf.Clamp(_config.BigDelay, 0.50f, 5f);
            SmallDelay = new WaitForSeconds(smallDelaySec);
            BigDelay = new WaitForSeconds(bigDelaySec);
            _startupRoutine = ServerMgr.Instance.StartCoroutine(StartupRoutine());
            NextTick(RegisterCommands);
        }

        void Unload()
        {
            if (_startupRoutine != null)
                ServerMgr.Instance.StopCoroutine(_startupRoutine);
            _dungeonTimer?.Destroy();
            _dungeonQueue.Clear();
            DestroyAllUis();
            RemoveAllDungeons();
        }

        object CanDropActiveItem(BasePlayer player)
        {
            if (RestoreUponDeath != null)
            {
                return null;
            }
            if (player == null)
                return null;
            var wasInDungeon = _wasInDungeonPlayers.FirstOrDefault(d => d == player);
            if (wasInDungeon != null)
            {
                var activeItem = player.GetActiveItem();
                if (activeItem != null)
                    return false;
            }
            return null;
        }

        object OnBackpackDrop(Item backpack, PlayerInventory inventory)
        {
            if (!_config.PreventDropBackpack)
                return null;
            var player = inventory?.containerMain?.playerOwner;
            if (RestoreUponDeath != null)
                return null;
            if (player == null)
                return null;
            var wasInDungeon = _wasInDungeonPlayers.FirstOrDefault(d => d == player);
            if (wasInDungeon != null)
                return true;
            return null;
        }

        object CanDropBackpack(ulong userID, Vector3 backpackPluginHook)
        {
            var player = BasePlayer.Find(userID.ToString());
            if (player == null)
                return null;
            var wasInDungeon = _wasInDungeonPlayers.FirstOrDefault(d => d == player);
            if (wasInDungeon != null)
                return false;
            return null;
        }

        object CanPickupEntity(BasePlayer player, BaseEntity entity)
        {
            if (player == null)
                return null;
            if (GetDungeonForPlayer(player) != null)
                return false;
            return null;
        }

        object CanDeployItem(BasePlayer player, Deployer deployer, ulong entityId)
        {
            if (player == null)
                return null;
            var dungeon = GetDungeonForPlayer(player);
            if (dungeon != null)
                return false;
            return null;
        }

        object CanBuild(Planner planner, Construction prefab, Construction.Target target)
        {
            var player = planner?.GetOwnerPlayer();
            if (player == null)
                return null;
            if (GetDungeonForPlayer(player) != null)
                return false;
            Vector3 buildPos = target.position;
            if (buildPos == Vector3.zero && target.socket != null && target.entity != null)
                buildPos = target.GetWorldPosition();
            float r = _config.RadiusSphere;
            float r2 = r * r;
            foreach (var dungeon in _activeDungeons)
            {
                if (dungeon.PortalPosition == Vector3.zero)
                    continue;
                float dx = buildPos.x - dungeon.PortalPosition.x;
                float dz = buildPos.z - dungeon.PortalPosition.z;
                if (dx * dx + dz * dz <= r2)
                    return false;
            }
            return null;
        }

        object OnPlayerCommand(BasePlayer player, string command, string[] args)
        {
            if (player == null)
                return null;
            if (GetDungeonForPlayer(player) == null)
                return null;
            if (_config.BlockCommands.Contains("/" + command.ToLower()))
            {
                NotifyPlayer(player, "BlockedCommands", 0);
                return true;
            }
            return null;
        }

        object OnServerCommand(ConsoleSystem.Arg arg)
        {
            if (arg == null || arg.cmd == null)
                return null;
            BasePlayer player = arg.Player();
            if (player != null && (GetDungeonForPlayer(player) != null))
            {
                if (_config.BlockCommands.Contains(arg.cmd.Name.ToLower()) || _config.BlockCommands.Contains(arg.cmd.FullName.ToLower()))
                {
                    NotifyPlayer(player, "BlockedCommands", 0);
                    return true;
                }
            }
            return null;
        }

        object OnCustomNpcTarget(ScientistNPC scientistNPC, BasePlayer player)
        {
            if (scientistNPC == null || !IsDungeonEntity(scientistNPC))
                return null;
            if (player == null || !player.userID.IsSteamId())
                return false;
            return null;
        }

        object CanEntityBeTargeted(BasePlayer player, AutoTurret turret)
        {
            if (turret == null || !IsDungeonEntity(turret))
                return null;
            if (player == null || !player.userID.IsSteamId())
                return false;
            return true;
        }

        object OnEntityEnter(TargetTrigger trigger, ScientistNPC scientistNPC)
        {
            if (trigger == null || scientistNPC == null || scientistNPC.net == null || scientistNPC.userID.IsSteamId())
                return null;
            AutoTurret autoTurret = trigger.GetComponentInParent<AutoTurret>();
            if (autoTurret == null || autoTurret.net == null)
                return null;
            if (IsDungeonEntity(autoTurret))
                return true;
            return null;
        }

        object OnPortalUse(BasePlayer player, BasePortal portal)
        {
            var activeDungeon = GetActiveDungeonByPortal(portal);
            if (activeDungeon == null)
                return null;
            if (!activeDungeon.Spawned)
            {
                NotifyPlayer(player, "DungeonStillSpawningMessage", 0);
                return false;
            }
            if (_config.LockDungeonToPlayer && !CanEnter(player, activeDungeon))
            {
                NotifyPlayer(player, "NoAccess", 0);
                return false;
            }
            return null;
        }

        void OnCorpsePopulate(ScientistNPC npc, NPCPlayerCorpse corpse)
        {
            if (npc == null || corpse == null)
                return;
            if (!IsDungeonEntity(npc))
                return;
            var activeDungeon = GetActiveDungeonByEntity(npc);
            if (activeDungeon == null)
                return;
            bool isBoss = npc.GetComponent<BossMonoBehaviour>() != null;
            var corpseData = corpse.gameObject.AddComponent<CorpseLootData>();
            corpseData.IsBoss = isBoss;
            corpseData.LootConfig = isBoss ? activeDungeon.TierConfig?.BossNpcConfig : activeDungeon.TierConfig?.NpcConfig;
            NextTick(() =>
            {
                if (corpse == null || corpse.IsDestroyed)
                    return;
                var storedData = corpse.GetComponent<CorpseLootData>();
                if (storedData == null)
                    return;
                if (storedData.LootConfig == null)
                    return;
                Effect.server.Run("assets/prefabs/weapons/flashbang/effects/fx-flashbang-boom.prefab", corpse.transform.position);
                if (corpse.containers == null || corpse.containers.Length == 0 || corpse.containers[0] == null)
                    return;
                var container = corpse.containers[0];
                container.Clear();
                var items = GetNpcLootItems(storedData.LootConfig);
                if (items == null || items.Count == 0)
                    return;
                int maxDifferentItems = storedData.IsBoss ? (activeDungeon?.TierConfig?.MaxItemsPerBossNpc ?? int.MaxValue) : (activeDungeon?.TierConfig?.MaxItemsPerNpc ?? int.MaxValue);
                var lootItems = items.OrderBy(_ => Random.value).ToList();
                int differentItemsCount = 0;
                foreach (var itemCfg in lootItems)
                {
                    if (differentItemsCount >= maxDifferentItems)
                        break;
                    if (Random.value * 100f > itemCfg.InclusionChancePercentage)
                        continue;
                    var def = ItemManager.FindItemDefinition(itemCfg.ShortName);
                    if (def == null)
                        continue;
                    int min = itemCfg.MinimumAmount;
                    int max = itemCfg.MaximumAmount;
                    if (min <= 0 || max <= 0)
                        continue;
                    if (max < min)
                    {
                        int t = min;
                        min = max;
                        max = t;
                    }
                    int amount = Random.Range(min, max + 1);
                    if (amount <= 0)
                        continue;
                    if (container.itemList.Count >= container.capacity)
                        break;
                    var item = ItemManager.Create(def, amount, itemCfg.SkinID);
                    if (item == null)
                        continue;
                    if (!string.IsNullOrEmpty(itemCfg.CustomName))
                        item.name = itemCfg.CustomName;
                    item.MoveToContainer(container);
                    differentItemsCount++;
                }
            });
        }

        void OnPlayerDeath(BasePlayer player, HitInfo info)
        {
            if (player == null || !player.userID.IsSteamId())
                return;
            ActiveDungeon dungeon;
            try
            {
                dungeon = GetDungeonForPlayer(player);
            }
            catch (Exception)
            {
                return;
            }
            if (dungeon == null)
                return;
            var basePortal = dungeon.BasePortal;
            var insidePortal = dungeon.InsidePortal;
            if (basePortal == null || insidePortal == null)
                return;
            if (basePortal.transform == null || insidePortal.transform == null)
                return;
            try
            {
                TeleportPlayerToOutsidePortal(player, dungeon);
            }
            catch (Exception) { }
            if (dungeon.Entities == null)
                return;
            foreach (var door in dungeon.Entities.OfType<Door>())
            {
                if (door == null || door.IsDestroyed || door.transform == null)
                    continue;
                try
                {
                    door.SetOpen(false);
                    door.SendNetworkUpdate();
                }
                catch (Exception) { }
            }
        }

        object CanRaidBlock(BasePlayer player)
        {
            var dungeon = GetDungeonForPlayer(player);
            if (dungeon != null)
                return false;
            return null;
        }

        void OnEntityDeath(BaseCombatEntity entity, HitInfo info)
        {
            if (entity == null || info?.InitiatorPlayer == null)
                return;
            ActiveDungeon dungeon = GetActiveDungeonByEntity(entity);
            if (dungeon == null || !dungeon.Spawned)
                return;
            bool isNpc = entity is ScientistNPC;
            bool isTurret = entity is AutoTurret;
            bool isBox = entity is StorageContainer;
            if (!isNpc && !isTurret && !isBox)
                return;
            RewardConfig r = dungeon.TierConfig?.RewardConfig;
            if (r == null)
                return;
            int econ =
                isNpc ? r.NpcEconomicsReward
                : isTurret ? r.TurretEconomicsReward
                : r.BoxEconomicsReward;
            int sr =
                isNpc ? r.NpcServerRewards
                : isTurret ? r.TurretServerRewards
                : r.BoxServerRewards;
            BasePlayer attacker = info.InitiatorPlayer;
            if (econ > 0 && Economics != null)
            {
                Economics.Call("Deposit", attacker.userID, (double)econ);
                attacker.ChatMessage(Msg(attacker.UserIDString, "EconRewardMessage", econ));
            }
            if (sr > 0 && ServerRewards != null)
            {
                ServerRewards.Call("AddPoints", attacker.userID, sr);
                attacker.ChatMessage(Msg(attacker.UserIDString, "ServerRewardMessage", sr));
            }
        }

        object OnEntityTakeDamage(BuildingBlock block, HitInfo info)
        {
            if (!IsDungeonEntity(block))
                return null;
            info.damageTypes?.ScaleAll(0f);
            return true;
        }

        object OnEntityTakeDamage(ScientistNPC scientistNPC, HitInfo info)
        {
            if (scientistNPC == null || info == null || info.Initiator == null)
                return null;
            if (info.Initiator is AutoTurret turret && IsDungeonEntity(turret))
            {
                info.damageTypes?.ScaleAll(0f);
                return null;
            }
            if (!IsDungeonEntity(scientistNPC))
                return null;
            var monitor = scientistNPC.GetComponent<NpcDamageMonitor>() ?? scientistNPC.gameObject.AddComponent<NpcDamageMonitor>();
            if (Time.time - monitor.LastHitTime > 2f)
                monitor.Hits = 0;
            monitor.Hits++;
            monitor.LastHitTime = Time.time;
            if (monitor.Hits >= 5)
            {
                monitor.Hits = 0;
                AttemptNpcReposition(scientistNPC);
            }
            return null;
        }

        object CanEntityTakeDamage(BuildingBlock block, HitInfo info)
        {
            if (!IsDungeonEntity(block))
                return null;
            info.damageTypes?.ScaleAll(0f);
            return false;
        }

        object CanEntityTakeDamage(BasePlayer victim, HitInfo info)
        {
            if (info?.Initiator == null || info.Initiator.net == null || !IsPlayer(victim))
                return null;
            if (info.Initiator is ScientistNPC && IsDungeonEntity(info.Initiator))
                return true;
            if (info.Initiator is AutoTurret && IsDungeonEntity(info.Initiator))
                return true;
            return null;
        }

        object CanEntityTakeDamage(AutoTurret autoTurret, HitInfo hitinfo)
        {
            if (autoTurret == null || hitinfo == null)
                return null;
            if (!IsDungeonEntity(autoTurret))
                return null;
            if (hitinfo.InitiatorPlayer == null || !IsPlayer(hitinfo.Initiator as BasePlayer))
                return false;
            return true;
        }

        object CanEntityTakeDamage(StorageContainer storageContainer, HitInfo hitinfo)
        {
            if (storageContainer == null || hitinfo == null)
                return null;
            if (!IsDungeonEntity(storageContainer))
                return null;
            if (hitinfo.InitiatorPlayer == null || !IsPlayer(hitinfo.Initiator as BasePlayer))
                return false;
            return true;
        }

        object CanEntityTakeDamage(Door victim, HitInfo hitinfo)
        {
            if (victim == null || hitinfo == null)
                return null;
            if (!IsDungeonEntity(victim))
                return null;
            if (hitinfo.InitiatorPlayer == null || !IsPlayer(hitinfo.Initiator as BasePlayer))
                return false;
            return true;
        }
        #endregion

        #region Data Initialization
        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                JObject raw;
                var threshold = new VersionNumber(3, 6, 0);
                VersionNumber parsedVersion = new VersionNumber(0, 0, 0);
                var hasVersion = TryReadRawConfig(out raw) && TryParseConfigVersion(raw, out parsedVersion);
                if (!hasVersion || parsedVersion < threshold)
                {
                    PrintWarning($"Legacy config detected {(hasVersion ? parsedVersion.ToString() : "unknown")} updating to {threshold}+.");
                    LoadDefaultConfig();
                    _config.Version = Version;
                    EnsureLootDataFiles();
                    InitializeTierInfoMap();
                    SaveConfig();
                    return;
                }
                var mutated = MigrateTiersObjectToArray(raw);
                _config = raw.ToObject<Configuration>() ?? new Configuration();
                var changed = false;
                if (_config.Version == null || _config.Version < Version)
                {
                    _config.Version = Version;
                    changed = true;
                }
                EnsureLootDataFiles();
                InitializeTierInfoMap();
                if (mutated || changed)
                    SaveConfig();
            }
            catch (Exception ex)
            {
                PrintError($"Error reading config: {ex.Message}");
                LoadDefaultConfig();
                _config.Version = Version;
                EnsureLootDataFiles();
                InitializeTierInfoMap();
                SaveConfig();
            }
        }

        protected override void LoadDefaultConfig()
        {
            PrintWarning("Creating a new configuration file");
            _config = new Configuration { Version = Version };
        }

        protected override void SaveConfig()
        {
            Config.WriteObject(_config, true);
        }

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(
                new Dictionary<string, string>
                {
                    ["AlreadyOwnsDungeonMessage"] = "You already own an active dungeon. You cannot purchase another one until it expires or is removed.",
                    ["DungeonAppeared"] = "A {0} has appeared at grid {1}!",
                    ["DungeonRemovedDetail"] = "Removed dungeon of tier {0} at grid {1}.",
                    ["DungeonSpawnedSuccess"] = "Dungeon spawned successfully at grid {0}!",
                    ["NpcSpawnNotLoaded"] = "NpcSpawn plugin is not loaded.",
                    ["DungeonStillSpawningMessage"] = "The dungeon is still spawning. Please wait until it's ready before entering.",
                    ["InsufficientFundsMessage"] = "You don't have enough funds to buy the {0} tier. Required: {1}.",
                    ["InvalidTierMessage"] = "Invalid tier name '{0}'. Available tiers: {1}.",
                    ["ThisTierDisabled"] = "This Tier is disabled for purchases",
                    ["MaxActiveDungeonsReached"] = "Cannot spawn: Maximum number of active dungeons reached.",
                    ["NoAccess"] = "You don't have permission to do this.",
                    ["PurchaseSuccessMessage"] = "You have successfully purchased the {0} tier!",
                    ["ReceivedRequest"] = "Your request has been added to the queue. Please wait.",
                    ["UsageCreateMessage"] = "Usage: /createdungeon <tier_name>",
                    ["CleanedUp"] = "All entities related to this plugin have been cleaned up.",
                    ["NoInactiveDungeonsToRemove"] = "There are no inactive dungeons to remove.",
                    ["WithdrawFailedMessage"] = "Failed to withdraw funds for {0}.",
                    ["DungeonBuyTitle"] = "Buy Dungeon",
                    ["BuyButton"] = "{0} ({1})",
                    ["BuyButtonWithName"] = "{0} ({1} {2})",
                    ["CloseButton"] = "Close",
                    ["DungeonRemovalCountdown"] = "Your dungeon will be removed in {0} minute(s)!",
                    ["BlockedCommands"] = "You cannot use commands inside a dungeon!",
                    ["EconRewardMessage"] = "You received {0} RP!",
                    ["ServerRewardMessage"] = "You received {0} RN!",
                    ["DungeonPurchased"] = "A {0} dungeon purchased by {1} has appeared at grid {2}!",
                    ["DungeonCooldownMessage"] = "You must wait {0} seconds before purchasing another dungeon.",
                    ["DungeonClearEconomyReward"] = "You received {0} RP for clearing the dungeon!",
                    ["DungeonClearServerReward"] = "You received {0} RN for clearing the dungeon!",
                    ["Dungeonclosed"] = "Dungeon closed. You have been teleported to the exit.",
                    ["DungeonClearXpReward"] = "You received {0} XP for clearing the dungeon!",
                    ["NoDungeonsToRemove"] = "There are no dungeons to remove.",
                    ["TooFarToRemove"] = "You must be within 10 meters of a dungeon to remove it.",
                    ["NotDungeonOwner"] = "You don't own an active dungeon.",
                    ["ConfigReloaded"] = "Configuration reloaded.",
                    ["PurchasesEnabled"] = "Purchases are now enabled.",
                    ["PurchasesDisabled"] = "Purchases are now disabled.",
                },
                this
            );
            lang.RegisterMessages(
                new Dictionary<string, string>
                {
                    ["AlreadyOwnsDungeonMessage"] = "Você já possui uma masmorra ativa. Não é possível comprar outra antes que ela expire ou seja removida.",
                    ["DungeonAppeared"] = "Uma {0} apareceu na grade {1}!",
                    ["DungeonRemovedDetail"] = "Masmorra de nível {0} removida na grade {1}.",
                    ["DungeonSpawnedSuccess"] = "Masmorra gerada com sucesso na grade {0}!",
                    ["NpcSpawnNotLoaded"] = "O plugin NpcSpawn não está carregado.",
                    ["DungeonStillSpawningMessage"] = "A masmorra ainda está sendo gerada. Por favor, aguarde até que esteja pronta antes de entrar.",
                    ["InsufficientFundsMessage"] = "Você não tem fundos suficientes para comprar o nível {0}. Requerido: {1}.",
                    ["InvalidTierMessage"] = "Nome de nível inválido '{0}'. Níveis disponíveis: {1}.",
                    ["ThisTierDisabled"] = "Esta dificuldade está desativada para compras",
                    ["MaxActiveDungeonsReached"] = "Não é possível gerar: número máximo de masmorras ativas alcançado.",
                    ["NoAccess"] = "Você não tem permissão para fazer isso.",
                    ["PurchaseSuccessMessage"] = "Você comprou com sucesso o nível {0}!",
                    ["ReceivedRequest"] = "Seu pedido foi adicionado à fila. Por favor aguarde.",
                    ["UsageCreateMessage"] = "Uso: /createdungeon <nome_do_nível>",
                    ["CleanedUp"] = "Todos os objetos relacionados a este plugin foram removidos.",
                    ["NoInactiveDungeonsToRemove"] = "Não há masmorras inativas para remover.",
                    ["WithdrawFailedMessage"] = "Falha ao retirar fundos para {0}.",
                    ["DungeonBuyTitle"] = "Comprar Masmorra",
                    ["BuyButton"] = "{0} ({1})",
                    ["BuyButtonWithName"] = "{0} ({1} {2})",
                    ["CloseButton"] = "Fechar",
                    ["DungeonRemovalCountdown"] = "Sua masmorra será removida em {0} minuto(s)!",
                    ["BlockedCommands"] = "Você não pode usar comandos dentro de uma masmorra!",
                    ["EconRewardMessage"] = "Você recebeu {0} RP!",
                    ["ServerRewardMessage"] = "Você recebeu {0} pontos de RN!",
                    ["DungeonPurchased"] = "Uma masmorra {0} comprada por {1} apareceu na grade {2}!",
                    ["DungeonCooldownMessage"] = "Você deve esperar {0} segundo(s) antes de comprar outra masmorra.",
                    ["DungeonClearEconomyReward"] = "Você recebeu {0} RP por limpar a masmorra!",
                    ["DungeonClearServerReward"] = "Você recebeu {0} pontos de RN por limpar a masmorra!",
                    ["Dungeonclosed"] = "Masmorra fechada. Você foi teleportado para a saída.",
                    ["DungeonClearXpReward"] = "Você recebeu {0} XP por limpar a masmorra!",
                    ["NoDungeonsToRemove"] = "Não há masmorras para remover.",
                    ["TooFarToRemove"] = "Você deve estar a até 10 metros de uma masmorra para removê-la.",
                    ["NotDungeonOwner"] = "Você não possui uma masmorra ativa.",
                    ["ConfigReloaded"] = "Configuração recarregada.",
                    ["PurchasesEnabled"] = "Compras agora estão habilitadas.",
                    ["PurchasesDisabled"] = "Compras agora estão desabilitadas.",
                },
                this,
                "pt-BR"
            );
            lang.RegisterMessages(
                new Dictionary<string, string>
                {
                    ["AlreadyOwnsDungeonMessage"] = "Du besitzt bereits ein aktives Verlies. Du kannst kein weiteres kaufen, bevor es abläuft oder entfernt wird.",
                    ["DungeonAppeared"] = "Ein {0} ist bei Gitter {1} erschienen!",
                    ["DungeonRemovedDetail"] = "Verlies der Stufe {0} bei Gitter {1} wurde entfernt.",
                    ["DungeonSpawnedSuccess"] = "Verlies erfolgreich bei Gitter {0} erstellt!",
                    ["NpcSpawnNotLoaded"] = "Das Plugin NpcSpawn ist nicht geladen.",
                    ["DungeonStillSpawningMessage"] = "Das Verlies wird noch erstellt. Bitte warte, bis es bereit ist, bevor du es betrittst.",
                    ["InsufficientFundsMessage"] = "Du hast nicht genug Geld, um die Stufe {0} zu kaufen. Erforderlich: {1}.",
                    ["InvalidTierMessage"] = "Ungültiger Stufenname '{0}'. Verfügbare Stufen: {1}.",
                    ["ThisTierDisabled"] = "Diese Schwierigkeitsstufe ist für Käufe deaktiviert",
                    ["MaxActiveDungeonsReached"] = "Kann nicht erstellt werden: Maximale Anzahl aktiver Verliese erreicht.",
                    ["NoAccess"] = "Du hast keine Berechtigung, dies zu tun.",
                    ["PurchaseSuccessMessage"] = "Du hast die Stufe {0} erfolgreich gekauft!",
                    ["ReceivedRequest"] = "Deine Anfrage wurde der Warteschlange hinzugefügt. Bitte warte.",
                    ["UsageCreateMessage"] = "Verwendung: /createdungeon <stufen_name>",
                    ["CleanedUp"] = "Alle mit diesem Plugin verbundenen Objekte wurden entfernt.",
                    ["NoInactiveDungeonsToRemove"] = "Es gibt keine inaktiven Verliese zum Entfernen.",
                    ["WithdrawFailedMessage"] = "Fehler beim Abheben der Mittel für {0}.",
                    ["DungeonBuyTitle"] = "Verlies kaufen",
                    ["BuyButton"] = "{0} ({1})",
                    ["BuyButtonWithName"] = "{0} ({1} {2})",
                    ["CloseButton"] = "Schließen",
                    ["DungeonRemovalCountdown"] = "Dein Verlies wird in {0} Minute(n) entfernt!",
                    ["BlockedCommands"] = "Du kannst in einem Verlies keine Befehle verwenden!",
                    ["EconRewardMessage"] = "Du hast {0} Münzen erhalten!",
                    ["ServerRewardMessage"] = "Du hast {0} RP erhalten!",
                    ["DungeonPurchased"] = "Ein {0} Verlies, gekauft von {1}, ist bei Gitter {2} erschienen!",
                    ["DungeonCooldownMessage"] = "Du musst {0} Sekunde(n) warten, bevor du ein weiteres Verlies kaufen kannst.",
                    ["DungeonClearEconomyReward"] = "Du hast {0} RP erhalten, weil du das Verlies vollständig geleert hast!",
                    ["DungeonClearServerReward"] = "Du hast {0} Serverpunkte erhalten, weil du das Verlies vollständig geleert hast!",
                    ["Dungeonclosed"] = "Verlies geschlossen. Du wurdest zum Ausgang teleportiert.",
                    ["DungeonClearXpReward"] = "Du hast {0} XP erhalten, weil du das Verlies vollständig geleert hast!",
                    ["NoDungeonsToRemove"] = "Es gibt keine Verliese zum Entfernen.",
                    ["TooFarToRemove"] = "Du musst dich innerhalb von 10 Metern eines Verlieses befinden, um es zu entfernen.",
                    ["NotDungeonOwner"] = "Du besitzt kein aktives Verlies.",
                    ["ConfigReloaded"] = "Konfiguration neu geladen.",
                    ["PurchasesEnabled"] = "Käufe sind jetzt aktiviert.",
                    ["PurchasesDisabled"] = "Käufe sind jetzt deaktiviert.",
                },
                this,
                "de"
            );
            lang.RegisterMessages(
                new Dictionary<string, string>
                {
                    ["AlreadyOwnsDungeonMessage"] = "Ya posees una mazmorra activa. No puedes comprar otra hasta que expire o sea eliminada.",
                    ["DungeonAppeared"] = "¡Una {0} ha aparecido en la cuadrícula {1}!",
                    ["DungeonRemovedDetail"] = "Mazmorra de nivel {0} eliminada en la cuadrícula {1}.",
                    ["DungeonSpawnedSuccess"] = "¡Mazmorra creada exitosamente en la cuadrícula {0}!",
                    ["NpcSpawnNotLoaded"] = "El plugin NpcSpawn no está cargado.",
                    ["DungeonStillSpawningMessage"] = "La mazmorra aún está generándose. Por favor, espera antes de entrar.",
                    ["InsufficientFundsMessage"] = "No tienes suficientes fondos para comprar el nivel {0}. Requerido: {1}.",
                    ["InvalidTierMessage"] = "Nombre de nivel inválido '{0}'. Niveles disponibles: {1}.",
                    ["ThisTierDisabled"] = "Esta dificultad está deshabilitada para compras",
                    ["MaxActiveDungeonsReached"] = "No se puede generar: se alcanzó el número máximo de mazmorras activas.",
                    ["NoAccess"] = "No tienes permiso para hacer esto.",
                    ["PurchaseSuccessMessage"] = "¡Has comprado con éxito el nivel {0}!",
                    ["ReceivedRequest"] = "Tu solicitud se ha añadido a la cola. Por favor, espera.",
                    ["UsageCreateMessage"] = "Uso: /createdungeon <nombre_del_nivel>",
                    ["CleanedUp"] = "Todos los objetos relacionados con este plugin han sido eliminados.",
                    ["NoInactiveDungeonsToRemove"] = "No hay mazmorras inactivas para eliminar.",
                    ["WithdrawFailedMessage"] = "Error al retirar fondos para {0}.",
                    ["DungeonBuyTitle"] = "Comprar Mazmorra",
                    ["BuyButton"] = "{0} ({1})",
                    ["BuyButtonWithName"] = "{0} ({1} {2})",
                    ["CloseButton"] = "Cerrar",
                    ["DungeonRemovalCountdown"] = "¡Tu mazmorra será eliminada en {0} minuto(s)!",
                    ["BlockedCommands"] = "¡No puedes usar comandos dentro de una mazmorra!",
                    ["EconRewardMessage"] = "¡Has recibido {0} RP!",
                    ["ServerRewardMessage"] = "¡Has recibido {0} puntos de RN!",
                    ["DungeonPurchased"] = "¡Una mazmorra {0} comprada por {1} ha aparecido en la cuadrícula {2}!",
                    ["DungeonCooldownMessage"] = "Debes esperar {0} segundo(s) antes de comprar otra mazmorra.",
                    ["DungeonClearEconomyReward"] = "¡Has recibido {0} RP por vaciar completamente la mazmorra!",
                    ["DungeonClearServerReward"] = "¡Has recibido {0} puntos de RN por vaciar completamente la mazmorra!",
                    ["Dungeonclosed"] = "Mazmorra cerrada. Has sido teletransportado a la salida.",
                    ["DungeonClearXpReward"] = "¡Has recibido {0} XP por vaciar completamente la mazmorra!",
                    ["NoDungeonsToRemove"] = "No hay mazmorras para eliminar.",
                    ["TooFarToRemove"] = "Debes estar a menos de 10 metros de una mazmorra para eliminarla.",
                    ["NotDungeonOwner"] = "No posees una mazmorra activa.",
                    ["ConfigReloaded"] = "Configuración recargada.",
                    ["PurchasesEnabled"] = "Las compras ahora están habilitadas.",
                    ["PurchasesDisabled"] = "Las compras ahora están deshabilitadas.",
                },
                this,
                "es"
            );
            lang.RegisterMessages(
                new Dictionary<string, string>
                {
                    ["AlreadyOwnsDungeonMessage"] = "У вас уже есть активное подземелье. Вы не можете приобрести другое, пока оно не истечет или не будет удалено.",
                    ["DungeonAppeared"] = "Подземелье {0} появилось в сетке {1}!",
                    ["DungeonRemovedDetail"] = "Удалено подземелье уровня {0} в сетке {1}.",
                    ["DungeonSpawnedSuccess"] = "Подземелье успешно создано в сетке {0}!",
                    ["NpcSpawnNotLoaded"] = "Плагин NpcSpawn не загружен.",
                    ["DungeonStillSpawningMessage"] = "Подземелье еще загружается. Пожалуйста, подождите, прежде чем войти.",
                    ["InsufficientFundsMessage"] = "У вас недостаточно средств для покупки уровня {0}. Нужно: {1}.",
                    ["InvalidTierMessage"] = "Неверное название уровня '{0}'. Доступные уровни: {1}.",
                    ["ThisTierDisabled"] = "Этот уровень сложности отключен для покупок",
                    ["MaxActiveDungeonsReached"] = "Невозможно создать: достигнуто максимальное количество активных подземелий.",
                    ["NoAccess"] = "У вас нет разрешения на это действие.",
                    ["PurchaseSuccessMessage"] = "Вы успешно приобрели уровень {0}!",
                    ["ReceivedRequest"] = "Ваш запрос был добавлен в очередь. Пожалуйста, подождите.",
                    ["UsageCreateMessage"] = "Использование: /createdungeon <название_уровня>",
                    ["CleanedUp"] = "Все объекты, связанные с этим плагином, были удалены.",
                    ["NoInactiveDungeonsToRemove"] = "Нет неактивных подземелий для удаления.",
                    ["WithdrawFailedMessage"] = "Ошибка при попытке вывести средства для {0}.",
                    ["DungeonBuyTitle"] = "Купить Подземелье",
                    ["BuyButton"] = "{0} ({1})",
                    ["BuyButtonWithName"] = "{0} ({1} {2})",
                    ["CloseButton"] = "Закрыть",
                    ["DungeonRemovalCountdown"] = "Ваше подземелье будет удалено через {0} минут(ы)!",
                    ["BlockedCommands"] = "Вы не можете использовать команды внутри подземелья!",
                    ["EconRewardMessage"] = "Вы получили {0} RP!",
                    ["ServerRewardMessage"] = "Вы получили {0} RN!",
                    ["DungeonPurchased"] = "Подземелье {0}, купленное {1}, появилось на сетке {2}!",
                    ["DungeonCooldownMessage"] = "Вы должны подождать {0} секунд(ы), прежде чем купить другое подземелье.",
                    ["DungeonClearEconomyReward"] = "Вы получили {0} RP за полное опустошение подземелья!",
                    ["DungeonClearServerReward"] = "Вы получили {0} RN за полное опустошение подземелья!",
                    ["Dungeonclosed"] = "Подземелье закрыто. Вы были телепортированы к выходу.",
                    ["DungeonClearXpReward"] = "Вы получили {0} XP за полное опустошение подземелья!",
                    ["NoDungeonsToRemove"] = "Нет подземелий для удаления.",
                    ["TooFarToRemove"] = "Вы должны находиться в пределах 10 метров от подземелья, чтобы удалить его.",
                    ["NotDungeonOwner"] = "Вы не являетесь владельцем активного подземелья.",
                    ["ConfigReloaded"] = "Конфигурация перезагружена.",
                    ["PurchasesEnabled"] = "Покупки теперь включены.",
                    ["PurchasesDisabled"] = "Покупки теперь отключены.",
                },
                this,
                "ru"
            );
        }
        #endregion

        #region Configuration
        private class Configuration
        {
            [JsonProperty("Enable Purchases")]
            public bool EnablePurchases { get; set; } = true;

            [JsonProperty("Use Notify Plugin")]
            public bool UseNotify { get; set; } = false;

            [JsonProperty("Enable Debug Logs")]
            public bool EnableDebugLogs { get; set; } = false;

            [JsonProperty("Enable Warning Logs")]
            public bool EnableWarningLogs { get; set; } = true;

            [JsonProperty("Enable Toast Messages")]
            public bool EnableShowToast { get; set; } = true;

            [JsonProperty("Prevent Drop Backpack")]
            public bool PreventDropBackpack { get; set; } = true;

            [JsonProperty("Teleport Player To Outside On Death")]
            public bool TeleportPlayerOnDeath { get; set; } = true;

            [JsonProperty("Spawn Point Configuration")]
            public SpawnPointConfiguration SpawnPointConfiguration { get; set; } = new SpawnPointConfiguration();

            [JsonProperty("Place Sphere on Dungeon Portal")]
            public bool EnablePlaceSphere { get; set; } = true;

            [JsonProperty("Radius Contruction Block on Dungeon Portal")]
            public int RadiusSphere { get; set; } = 20;

            [JsonProperty("Custom AutoTurret Behavior (Use in case AutoTurrets aren't shooting)")]
            public bool CustomAutoTurretBehavior { get; set; } = false;

            [JsonProperty("NightVision Plugin Time On Leaving Dungeon(-1 for no override)")]
            public int NightVisionTime { get; set; } = 12;

            [JsonProperty("Lock dungeon for first player")]
            public bool LockDungeonToPlayer { get; set; } = true;

            [JsonProperty("Economy Plugin (1 - Economics, 2 - ServerRewards, 3 - Custom)")]
            public int EconomyPlugin { get; set; } = 3;

            [JsonProperty("Custom Economy Item Name")]
            public string CustomEconomyItemName { get; set; } = "scrap";

            [JsonProperty("Custom Economy Display Name")]
            public string CustomEconomyDisplayName { get; set; } = "Scrap";

            [JsonProperty("Economics Display Name")]
            public string EconomicsDisplayName { get; set; } = "RP";

            [JsonProperty("ServerRewards Display Name")]
            public string ServerRewardsDisplayName { get; set; } = "RN";

            public string GetEconomyItemName()
            {
                return EconomyPlugin switch
                {
                    1 => "economics",
                    2 => "serverrewards",
                    _ => CustomEconomyItemName,
                };
            }

            public string GetEconomyDisplayName()
            {
                return EconomyPlugin switch
                {
                    1 => EconomicsDisplayName,
                    2 => ServerRewardsDisplayName,
                    _ => CustomEconomyDisplayName,
                };
            }

            [JsonProperty("Allow team members")]
            public bool AllowTeam { get; set; } = true;

            [JsonProperty("Allow friends")]
            public bool AllowFriends { get; set; } = true;

            [JsonProperty("Small Delay (seconds) – increase if FPS drops")]
            public float SmallDelay { get; set; } = 0.15f;

            [JsonProperty("Big Delay (seconds) – increase if FPS drops")]
            public float BigDelay { get; set; } = 0.50f;

            [JsonProperty("Dungeon Settings")]
            public DungeonSpawnSettings DungeonSpawn { get; set; } = new DungeonSpawnSettings();

            [JsonProperty("Blocked commands inside a dungeon", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public HashSet<string> BlockCommands { get; set; } = new HashSet<string> { "/remove", "/tpa", "remove.toggle" };

            [JsonProperty("Tiers", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public List<DungeonTierConfig> Tiers { get; set; } =
                new List<DungeonTierConfig>
                {
                    new DungeonTierConfig
                    {
                        TierName = "Easy",
                        MapName = "Dungeon: Easy",
                        MarkerColorHex = "#3cd834",
                        BuildingGradeSelection = 3,
                        ContainerColor = 0,
                        DungeonRooms = 1,
                        DungeonRoomSize = 5,
                        BuyCost = 300,
                        EntitySpawnLimits = new EntitySpawnLimits
                        {
                            NpcsCounts = 9,
                            BossesCounts = 1,
                            TurretsCounts = 5,
                            LootBoxesCounts = 5,
                        },
                        AutoTurretConfig = new TurretConfig { Health = 300, WeaponShortName = "pistol.revolver" },
                        LootBoxSkinID = 2998755525,
                        MaxItemsPerBox = 3,
                        MaxItemsPerNpc = 3,
                        MaxItemsPerBossNpc = 3,
                        NpcConfig = new NpcConfig
                        {
                            Name = "Wild Scavenger",
                            Health = 100,
                            DamageScale = 0.5f,
                            WearItems = new WearConfig
                            {
                                Items = new List<WearItemConfig>
                                {
                                    new() { ShortName = "tshirt.long", SkinID = 10118 },
                                    new() { ShortName = "burlap.gloves", SkinID = 949616124 },
                                    new() { ShortName = "attire.snowman.helmet", SkinID = 0 },
                                    new() {
// ... [Code preview truncated due to length. Full source in attached file] ...

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