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

FREE Stadia : 1.0.0 1.0.0

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

namespace Oxide.Plugins
{
    [Info("Stadia", "fufeldev", "1.0.0")]
    public class Stadia : RustPlugin
    {
        [PluginReference] private Plugin FBradleyRoute;

        private const string UiRoot = "Stadia_UI";
        private const string PhaseBackplate = "Hudaima_TopStats_Backplates_1";
        private const string PhaseTime = "phase_time";
        private const string PhaseWarmup = "phase_warmup";
        private const string PhasePvp = "phase_pvp";
        private const string PhaseBuild = "phase_build";
        private const string PhaseRaid = "phase_raid";
        private const int PhaseWarmupSeconds = 300;
        private const int PhasePvpSeconds = 1200;
        private const int PhaseBuildSeconds = 3600;
        private const int PhaseRaidSeconds = 7200;
        private const float BradleySpawnDelay = 180f;
        private const float HeliSpawnDelay = 420f;
        private const string HeliPrefab = "assets/prefabs/npc/patrol helicopter/patrolhelicopter.prefab";

        private readonly Dictionary<string, string> _imageStorageIds = new Dictionary<string, string>();
        private readonly HashSet<ulong> _openedPlayers = new HashSet<ulong>();
        private readonly Dictionary<ulong, int> _kills = new Dictionary<ulong, int>();
        private readonly Dictionary<ulong, int> _deaths = new Dictionary<ulong, int>();

        private string _backplatePng;
        private string _phaseTimePng;
        private string _phaseBuildPng;
        private string _phaseName = PhaseRaid;
        private int _phaseRemainingSeconds;
        private long _phaseEndsAtUnix;
        private Timer _phaseTimer;
        private Timer _saveTimer;
        private Timer _bradleySpawnTimer;
        private Timer _heliSpawnTimer;

        private class StoredData
        {
            public string WipeId;
            public string CurrentPhase;
            public long PhaseEndsAtUnix;
            public long SavedAtUnix;
        }

        private StoredData _data = new StoredData();

        private static readonly Dictionary<string, string> ImageFiles = new Dictionary<string, string>
        {
            { PhaseBackplate, "Hudaima_TopStats_Backplates_1.png" },
            { PhaseTime, "phase time.png" },
            { PhaseBuild, "phase build.png" }
        };

        private void OnServerInitialized()
        {
            LoadImageAssets();
            LoadData();
            RestorePhase();
            _phaseTimer = timer.Every(1f, TickPhase);
            _saveTimer = timer.Every(120f, SavePhaseData);
            timer.Once(1f, ShowAll);
        }

        private void OnPlayerInit(BasePlayer player)
        {
            QueueShow(player);
        }

        private void OnPlayerConnected(BasePlayer player)
        {
            QueueShow(player);
        }

        private void OnPlayerRespawned(BasePlayer player)
        {
            QueueShow(player);
        }

        private void QueueShow(BasePlayer player)
        {
            if (player == null || player.IsNpc)
            {
                return;
            }

            timer.Once(2f, () =>
            {
                if (player != null && player.IsConnected && !player.IsNpc)
                {
                    Show(player);
                }
            });
        }

        private void LoadImageAssets()
        {
            var imageDir = Path.Combine(Interface.Oxide.DataDirectory, "Stadia", "Images");
            Directory.CreateDirectory(imageDir);
            _imageStorageIds.Clear();
            foreach (var kv in ImageFiles)
            {
                var path = Path.Combine(imageDir, kv.Value);
                if (!File.Exists(path))
                {
                    PrintWarning($"[UIAssets] Missing PNG file: {path}");
                    continue;
                }

                try
                {
                    var bytes = File.ReadAllBytes(path);
                    _imageStorageIds[kv.Key] = FileStorage.server.Store(bytes, FileStorage.Type.png, CommunityEntity.ServerInstance.net.ID).ToString();
                }
                catch (Exception ex)
                {
                    PrintWarning($"[UIAssets] Failed to load {kv.Key}: {ex.Message}");
                }
            }

            _backplatePng = Img(PhaseBackplate);
            _phaseTimePng = Img(PhaseTime);
            _phaseBuildPng = Img(PhaseBuild);
        }

        private string Img(string key)
        {
            return _imageStorageIds.TryGetValue(key, out var stored) ? stored : string.Empty;
        }

        private void LoadData()
        {
            try
            {
                _data = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(Name) ?? new StoredData();
            }
            catch
            {
                _data = new StoredData();
            }
        }

        private void SaveData()
        {
            Interface.Oxide.DataFileSystem.WriteObject(Name, _data);
        }

        private void SavePhaseData()
        {
            if (_data == null) _data = new StoredData();
            _data.WipeId = SaveRestore.WipeId;
            _data.CurrentPhase = _phaseName;
            _data.PhaseEndsAtUnix = _phaseEndsAtUnix;
            _data.SavedAtUnix = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            SaveData();
        }

        private void RestorePhase()
        {
            if (_data == null) _data = new StoredData();
            if (IsNewWipe())
            {
                _data.CurrentPhase = PhaseWarmup;
                _data.PhaseEndsAtUnix = 0;
                _data.WipeId = SaveRestore.WipeId;
                SetPhase(PhaseWarmup, false);
                return;
            }

            string phase = NormalizePhase(_data.CurrentPhase);
            if (string.IsNullOrEmpty(phase) || _data.PhaseEndsAtUnix <= 0)
            {
                SetPhase(PhaseWarmup, false);
                return;
            }

            long now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            long endsAt = _data.PhaseEndsAtUnix;
            for (int i = 0; i < 10000 && endsAt <= now; i++)
            {
                phase = GetNextPhase(phase);
                endsAt += GetPhaseSeconds(phase);
            }

            if (endsAt <= now)
            {
                SetPhase(PhaseBuild, false);
                return;
            }

            SetPhase(phase, false, Math.Max(1, (int)(endsAt - now)));
            _phaseEndsAtUnix = endsAt;
            SavePhaseData();
        }

        private bool IsNewWipe()
        {
            string wipeId = SaveRestore.WipeId;
            if (!string.IsNullOrEmpty(_data.WipeId) && !string.IsNullOrEmpty(wipeId) && _data.WipeId != wipeId) return true;
            if (!string.IsNullOrEmpty(_data.WipeId) || _data.SavedAtUnix <= 0 || SaveRestore.SaveCreatedTime.Year < 2020) return false;
            long saveCreatedAt = new DateTimeOffset(SaveRestore.SaveCreatedTime.ToUniversalTime()).ToUnixTimeSeconds();
            return saveCreatedAt > _data.SavedAtUnix;
        }

        private string NormalizePhase(string phase)
        {
            if (string.IsNullOrWhiteSpace(phase)) return null;
            phase = phase.ToLowerInvariant();
            if (phase == "warmup" || phase == PhaseWarmup || phase == "time" || phase == PhaseTime) return PhaseWarmup;
            if (phase == "pvp" || phase == PhasePvp) return PhasePvp;
            if (phase == "build" || phase == PhaseBuild) return PhaseBuild;
            if (phase == "raid" || phase == PhaseRaid) return PhaseRaid;
            return null;
        }

        private string GetNextPhase(string phase)
        {
            if (phase == PhaseWarmup) return PhaseBuild;
            if (phase == PhaseBuild) return PhasePvp;
            if (phase == PhasePvp) return PhaseRaid;
            return PhaseBuild;
        }

        [ChatCommand("stadia.show")]
        private void ShowUICommand(BasePlayer player, string command, string[] args)
        {
            Show(player);
        }

        [ChatCommand("stadia.hide")]
        private void HideUICommand(BasePlayer player, string command, string[] args)
        {
            Hide(player);
        }

        [ChatCommand("stadia.phase")]
        private void PhaseChatCommand(BasePlayer player, string command, string[] args)
        {
            if (player == null || !player.IsAdmin) return;
            SetPhase(args);
        }

        [ChatCommand("stage")]
        private void StageChatCommand(BasePlayer player, string command, string[] args)
        {
            PhaseChatCommand(player, command, args);
        }

        [ConsoleCommand("stadia.show")]
        private void ShowConsoleCommand(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null)
            {
                ShowAll();
                return;
            }

            Show(player);
        }

        [ConsoleCommand("stadia.hide")]
        private void HideConsoleCommand(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null)
            {
                HideAll();
                return;
            }

            Hide(player);
        }

        [ConsoleCommand("stadia.phase")]
        private void PhaseConsoleCommand(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player != null && !player.IsAdmin) return;
            if (arg.Args == null || arg.Args.Length == 0) return;
            SetPhase(arg.Args[0].ToString(), true, arg.Args.Length > 1 ? ParsePhaseSeconds(arg.Args[1].ToString()) : -1);
        }

        [ConsoleCommand("stage")]
        private void StageConsoleCommand(ConsoleSystem.Arg arg)
        {
            PhaseConsoleCommand(arg);
        }

        [ConsoleCommand("stadia.test")]
        private void TestConsoleCommand(ConsoleSystem.Arg arg)
        {
            ShowAll();
        }

        private void OnPlayerDeath(BasePlayer player, HitInfo info)
        {
            if (player == null || player.IsNpc)
            {
                return;
            }

            if (!_deaths.ContainsKey(player.userID))
            {
                _deaths[player.userID] = 0;
            }

            _deaths[player.userID]++;

            if (info != null && (info.InitiatorPlayer == player || info.damageTypes.Has(DamageType.Suicide)))
            {
                UpdatePlayer(player);
                return;
            }

            var killer = info?.InitiatorPlayer;
            if (killer != null && killer != player && !killer.IsNpc)
            {
                if (!_kills.ContainsKey(killer.userID))
                {
                    _kills[killer.userID] = 0;
                }

                _kills[killer.userID]++;
                UpdatePlayer(killer);
            }

            UpdatePlayer(player);
        }

        private void SetPhase(string[] args)
        {
            if (args == null || args.Length == 0)
            {
                return;
            }

            SetPhase(args[0], true, args.Length > 1 ? ParsePhaseSeconds(args[1]) : -1);
        }

        private void SetPhase(string phase, Boolean notify = true, Int32 customSeconds = -1)
        {
            phase = NormalizePhase(phase);
            if (string.IsNullOrEmpty(phase)) return;

            _phaseName = phase;
            _phaseRemainingSeconds = customSeconds > 0 ? customSeconds : GetPhaseSeconds(_phaseName);
            _phaseEndsAtUnix = DateTimeOffset.UtcNow.ToUnixTimeSeconds() + Math.Max(1, _phaseRemainingSeconds);
            SavePhaseData();
            if (notify) Interface.CallHook("OnStadiaPhaseChanged", _phaseName);
            if (phase == PhasePvp && notify)
            {
                SchedulePvpSpawns();
            }
            else if (phase != PhasePvp)
            {
                CancelPvpSpawns();
            }
            RebuildOpened();
        }

        private Int32 ParsePhaseSeconds(string value)
        {
            if (String.IsNullOrWhiteSpace(value)) return -1;
            value = value.Trim().ToLowerInvariant();

            if (Int32.TryParse(value, out Int32 seconds)) return seconds;
            if (value.EndsWith("s") && Int32.TryParse(value.Substring(0, value.Length - 1), out seconds)) return seconds;
            if (value.EndsWith("m") && Int32.TryParse(value.Substring(0, value.Length - 1), out seconds)) return seconds * 60;
            if (value.EndsWith("h") && Int32.TryParse(value.Substring(0, value.Length - 1), out seconds)) return seconds * 3600;

            return -1;
        }

        private void TickPhase()
        {
            if (_phaseRemainingSeconds <= 0)
            {
                return;
            }

            _phaseRemainingSeconds--;
            if (_phaseRemainingSeconds > 0)
            {
                UpdatePhaseTime();
                return;
            }

            if (_phaseName == PhaseWarmup)
            {
                SetPhase(PhaseBuild);
                return;
            }

            if (_phaseName == PhaseBuild)
            {
                SetPhase(PhasePvp);
                return;
            }

            if (_phaseName == PhasePvp)
            {
                SetPhase(PhaseRaid);
                return;
            }

            UpdatePhaseTime();
        }

        private void Show(BasePlayer player)
        {
            if (player == null || !player.IsConnected)
            {
                return;
            }

            _openedPlayers.Add(player.userID);
            CuiHelper.DestroyUi(player, UiRoot);
            CuiHelper.AddUi(player, CreateUI(player));
        }

        private void ShowAll()
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player == null || !player.IsConnected || player.IsNpc)
                {
                    continue;
                }

                Show(player);
            }
        }

        private void Hide(BasePlayer player)
        {
            if (player == null)
            {
                return;
            }

            _openedPlayers.Remove(player.userID);
            CuiHelper.DestroyUi(player, UiRoot);
        }

        private void HideAll()
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player == null || !player.IsConnected || player.IsNpc)
                {
                    continue;
                }

                Hide(player);
            }
        }

        private void UpdateAll()
        {
            if (_openedPlayers.Count == 0)
            {
                return;
            }

            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player == null || !player.IsConnected || player.IsNpc)
                {
                    continue;
                }

                if (_openedPlayers.Contains(player.userID))
                {
                    CuiHelper.AddUi(player, CreateUpdateContainer(player));
                }
            }
        }

        private void RebuildOpened()
        {
            if (_openedPlayers.Count == 0) return;
            List<ulong> opened = new List<ulong>(_openedPlayers);
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player == null || !player.IsConnected || player.IsNpc) continue;
                if (!opened.Contains(player.userID)) continue;
                Show(player);
            }
        }

        private void UpdatePlayer(BasePlayer player)
        {
            if (player == null || !player.IsConnected || player.IsNpc)
            {
                return;
            }

            if (!_openedPlayers.Contains(player.userID))
            {
                return;
            }

            CuiHelper.AddUi(player, CreateUpdateContainer(player));
        }

        private void UpdatePhaseTime()
        {
            if (_openedPlayers.Count == 0)
            {
                return;
            }

            var container = CreatePhaseTimeUpdateContainer();
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player == null || !player.IsConnected || player.IsNpc)
                {
                    continue;
                }

                if (_openedPlayers.Contains(player.userID))
                {
                    CuiHelper.AddUi(player, container);
                }
            }
        }

        private int GetKills(ulong userId)
        {
            return _kills.TryGetValue(userId, out var value) ? value : 0;
        }

        private int GetDeaths(ulong userId)
        {
            return _deaths.TryGetValue(userId, out var value) ? value : 0;
        }

        private float GetKd(ulong userId)
        {
            var deaths = GetDeaths(userId);
            return deaths <= 0 ? GetKills(userId) : (float)GetKills(userId) / deaths;
        }

        private CuiElementContainer CreateUI(BasePlayer player)
        {
            var container = new CuiElementContainer();

            container.Add(new CuiElement
            {
                Name = UiRoot,
                Parent = "Hud",
                Components =
                {
                    new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" }
                }
            });

            AddBackplate(container);
            AddPhaseText(container);
            AddKills(container, player);
            AddDeaths(container, player);
            AddKd(container, player);

            return container;
        }

        private CuiElementContainer CreateUpdateContainer(BasePlayer player)
        {
            var container = new CuiElementContainer();

            container.Add(new CuiElement
            {
                Name = "Hudaima_TopStats_Backplates_1",
                Update = true,
                Components =
                {
                    new CuiRawImageComponent { Color = "1 1 1 1", Png = CurrentBackplatePng() }
                }
            });

            container.Add(new CuiElement
            {
                Name = "Hudaima_Warmup_Title_Text_1",
                Update = true,
                Components =
                {
                    new CuiTextComponent { Text = CurrentPhaseText(), FontSize = 12, Align = TextAnchor.MiddleLeft, Color = "0.925 0.925 0.925 1", Font = "robotocondensed-bold.ttf" }
                }
            });

            container.Add(new CuiElement
            {
                Name = "Hudaima_Warmup_Value_Text_1",
                Update = true,
                Components =
                {
                    new CuiTextComponent { Text = CurrentPhaseValueText(), FontSize = 11, Align = TextAnchor.MiddleCenter, Color = "0.925 0.925 0.925 1", Font = "robotocondensed-bold.ttf" }
                }
            });

            container.Add(new CuiElement
            {
                Name = "Hudaima_Kills_Value_Text_1",
                Update = true,
                Components =
                {
                    new CuiTextComponent { Text = GetKills(player.userID).ToString(), FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1.000 0.278 0.278 1", Font = "robotocondensed-bold.ttf" }
                }
            });

            container.Add(new CuiElement
            {
                Name = "Hudaima_Death_Value_Text_1",
                Update = true,
                Components =
                {
                    new CuiTextComponent { Text = GetDeaths(player.userID).ToString(), FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1.000 0.278 0.278 1", Font = "robotocondensed-bold.ttf" }
                }
            });

            container.Add(new CuiElement
            {
                Name = "Hudaima_Kd_Value_Text_1",
                Update = true,
                Components =
                {
                    new CuiTextComponent { Text = GetKd(player.userID).ToString("0.0"), FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1.000 0.278 0.278 1", Font = "robotocondensed-bold.ttf" }
                }
            });

            return container;
        }

        private CuiElementContainer CreatePhaseTimeUpdateContainer()
        {
            var container = new CuiElementContainer();

            container.Add(new CuiElement
            {
                Name = "Hudaima_Warmup_Value_Text_1",
                Update = true,
                Components =
                {
                    new CuiTextComponent { Text = CurrentPhaseValueText(), FontSize = 11, Align = TextAnchor.MiddleCenter, Color = "0.925 0.925 0.925 1", Font = "robotocondensed-bold.ttf" }
                }
            });

            return container;
        }

        private void AddBackplate(CuiElementContainer container)
        {
            container.Add(new CuiElement
            {
                Name = "Hudaima_TopStats_Backplates_1",
                Parent = UiRoot,
                Components =
                {
                    new CuiRawImageComponent { Color = "1 1 1 1", Png = CurrentBackplatePng() },
                    new CuiRectTransformComponent { AnchorMin = "0.0000 1.0000", AnchorMax = "0.0000 1.0000", OffsetMin = "20.6667 -85.3333", OffsetMax = "237.3333 -24.0000" }
                }
            });
        }

        private void AddPhaseText(CuiElementContainer container)
        {
            container.Add(new CuiElement
            {
                Name = "Hudaima_Warmup_Title_Text_1",
                Parent = UiRoot,
                Components =
                {
                    new CuiTextComponent { Text = CurrentPhaseText(), FontSize = 12, Align = TextAnchor.MiddleLeft, Color = "0.925 0.925 0.925 1", Font = "robotocondensed-bold.ttf" },
                    new CuiRectTransformComponent { AnchorMin = "0.0000 1.0000", AnchorMax = "0.0000 1.0000", OffsetMin = "34.0000 -46.0000", OffsetMax = "138.0000 -30.0000" }
                }
            });

            container.Add(new CuiElement
            {
                Name = "Hudaima_Warmup_Value_Text_1",
                Parent = UiRoot,
                Components =
                {
                    new CuiTextComponent { Text = CurrentPhaseValueText(), FontSize = 11, Align = TextAnchor.MiddleCenter, Color = "0.925 0.925 0.925 1", Font = "robotocondensed-bold.ttf" },
                    new CuiRectTransformComponent { AnchorMin = "0.0000 1.0000", AnchorMax = "0.0000 1.0000", OffsetMin = "179.0000 -46.6667", OffsetMax = "228.3333 -30.0000" }
                }
            });
        }

        private void AddKills(CuiElementContainer container, BasePlayer player)
        {
            var kills = GetKills(player.userID);
            container.Add(new CuiElement
            {
                Name = "Hudaima_Kills_Value_Text_1",
                Parent = UiRoot,
                Components =
                {
                    new CuiTextComponent { Text = kills.ToString(), FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1.000 0.278 0.278 1", Font = "robotocondensed-bold.ttf" },
                    new CuiRectTransformComponent { AnchorMin = "0.0000 1.0000", AnchorMax = "0.0000 1.0000", OffsetMin = "30.0000 -80.0000", OffsetMax = "60.0000 -62.6667" }
                }
            });

            container.Add(new CuiElement
            {
                Name = "Hudaima_Kills_Label_Text_1",
                Parent = UiRoot,
                Components =
                {
                    new CuiTextComponent { Text = "KILLS", FontSize = 8, Align = TextAnchor.MiddleLeft, Color = "0.925 0.925 0.925 1", Font = "robotocondensed-bold.ttf" },
                    new CuiRectTransformComponent { AnchorMin = "0.0000 1.0000", AnchorMax = "0.0000 1.0000", OffsetMin = "53.3333 -79.3333", OffsetMax = "88.0000 -67.3333" }
                }
            });
        }

        private void AddDeaths(CuiElementContainer container, BasePlayer player)
        {
            var deaths = GetDeaths(player.userID);
            container.Add(new CuiElement
            {
                Name = "Hudaima_Death_Value_Text_1",
                Parent = UiRoot,
                Components =
                {
                    new CuiTextComponent { Text = deaths.ToString(), FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1.000 0.278 0.278 1", Font = "robotocondensed-bold.ttf" },
                    new CuiRectTransformComponent { AnchorMin = "0.0000 1.0000", AnchorMax = "0.0000 1.0000", OffsetMin = "101.6667 -80.0000", OffsetMax = "129.6667 -62.6667" }
                }
            });

            container.Add(new CuiElement
            {
                Name = "Hudaima_Death_Label_Text_1",
                Parent = UiRoot,
                Components =
                {
                    new CuiTextComponent { Text = "DEATH", FontSize = 8, Align = TextAnchor.MiddleLeft, Color = "0.925 0.925 0.925 1", Font = "robotocondensed-bold.ttf" },
                    new CuiRectTransformComponent { AnchorMin = "0.0000 1.0000", AnchorMax = "0.0000 1.0000", OffsetMin = "121.3333 -79.3333", OffsetMax = "156.0000 -67.3333" }
                }
            });
        }

        private void AddKd(CuiElementContainer container, BasePlayer player)
        {
            var kd = GetKd(player.userID);
            container.Add(new CuiElement
            {
                Name = "Hudaima_Kd_Value_Text_1",
                Parent = UiRoot,
                Components =
                {
                    new CuiTextComponent { Text = kd.ToString("0.0"), FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1.000 0.278 0.278 1", Font = "robotocondensed-bold.ttf" },
                    new CuiRectTransformComponent { AnchorMin = "0.0000 1.0000", AnchorMax = "0.0000 1.0000", OffsetMin = "175.6667 -80.0000", OffsetMax = "216.3333 -62.6667" }
                }
            });

            container.Add(new CuiElement
            {
                Name = "Hudaima_Kd_Label_Text_1",
                Parent = UiRoot,
                Components =
                {
                    new CuiTextComponent { Text = "KD", FontSize = 8, Align = TextAnchor.MiddleLeft, Color = "0.925 0.925 0.925 1", Font = "robotocondensed-bold.ttf" },
                    new CuiRectTransformComponent { AnchorMin = "0.0000 1.0000", AnchorMax = "0.0000 1.0000", OffsetMin = "206.0000 -79.3333", OffsetMax = "223.3333 -67.3333" }
                }
            });
        }

        private string CurrentBackplatePng()
        {
            if (_phaseName == PhaseWarmup || _phaseName == PhasePvp)
            {
                return _phaseTimePng;
            }

            if (_phaseName == PhaseBuild)
            {
                return _phaseBuildPng;
            }

            return _backplatePng;
        }

        private string CurrentPhaseText()
        {
            if (_phaseName == PhaseWarmup)
            {
                return "WARMUP TIME";
            }

            if (_phaseName == PhasePvp)
            {
                return "PVP PHASE";
            }

            if (_phaseName == PhaseBuild)
            {
                return "BUILD PHASE";
            }

            return "RAID PHASE";
        }

        private string CurrentPhaseValueText()
        {
            var seconds = Mathf.Max(0, _phaseRemainingSeconds);
            if (seconds >= 3600)
            {
                return TimeSpan.FromSeconds(seconds).ToString(@"hh\:mm\:ss");
            }

            return TimeSpan.FromSeconds(seconds).ToString(@"mm\:ss");
        }

        [HookMethod("GetCurrentPhase")]
        public string GetCurrentPhase() => _phaseName;

        private int GetPhaseSeconds(string phase)
        {
            if (phase == PhaseWarmup)
            {
                return PhaseWarmupSeconds;
            }

            if (phase == PhasePvp)
            {
                return PhasePvpSeconds;
            }

            if (phase == PhaseBuild)
            {
                return PhaseBuildSeconds;
            }

            return PhaseRaidSeconds;
        }

        private void SchedulePvpSpawns()
        {
            CancelPvpSpawns();
            _bradleySpawnTimer = timer.Once(BradleySpawnDelay, SpawnBradleyApc);
            _heliSpawnTimer = timer.Once(HeliSpawnDelay, SpawnPatrolHeli);
        }

        private void CancelPvpSpawns()
        {
            DestroyTimer(ref _bradleySpawnTimer);
            DestroyTimer(ref _heliSpawnTimer);
        }

        private void SpawnBradleyApc()
        {
            if (FBradleyRoute != null)
            {
                var result = FBradleyRoute.Call("SpawnRouteBradley");
                if (result != null)
                {
                    Puts($"[PVP] Bradley spawned via FBradleyRoute at route point, netId={result}");
                    return;
                }
                Puts("[PVP] SpawnRouteBradley returned null, falling back to BradleySpawner");
            }
            else
            {
                Puts("[PVP] FBradleyRoute plugin not loaded, using BradleySpawner");
            }

            var spawner = BradleySpawner.singleton;
            if (spawner == null)
            {
                Puts("[PVP] BradleySpawner.singleton is null");
                return;
            }
            if (spawner.spawned != null && spawner.spawned.IsAlive())
            {
                Puts("[PVP] Bradley already alive, skip");
                return;
            }
            spawner.spawned = null;
            spawner.SpawnBradley();
            Puts("[PVP] Bradley spawned via BradleySpawner.SpawnBradley()");
        }

        private void SpawnPatrolHeli()
        {
            var entity = GameManager.server.CreateEntity(HeliPrefab);
            if (entity == null) return;
            entity.Spawn();
        }

        private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
        {
            if (_phaseName != PhasePvp) return;
            if (entity == null || info == null || info.damageTypes == null) return;
            if (info.WeaponPrefab == null) return;

            string weaponName = info.WeaponPrefab.name;
            if (!weaponName.Contains("rocket") && !weaponName.Contains("explosive.timed")) return;

            if (entity is BasePlayer || entity is BradleyAPC) return;

            info.damageTypes.Clear();
        }

        private void Unload()
        {
            SavePhaseData();
            DestroyTimer(ref _phaseTimer);
            DestroyTimer(ref _saveTimer);
            CancelPvpSpawns();
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player == null || !player.IsConnected || player.IsNpc)
                {
                    continue;
                }

                CuiHelper.DestroyUi(player, UiRoot);
            }

            _openedPlayers.Clear();
        }

        private void DestroyTimer(ref Timer value)
        {
            if (value == null) return;
            value.Destroy();
            value = null;
        }

        private void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            if (player == null)
            {
                return;
            }

            _openedPlayers.Remove(player.userID);
        }
    }
}

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