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

FREE EnergySystem : 1.0.13 1.0.13

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using UnityEngine;
using Oxide.Game.Rust.Cui;
using Rust;

namespace Oxide.Plugins
{
    [Info("EnergySystem", "YourName", "1.0.13")]
    [Description("Система энергии с UI-шкалой, зонами и ограничениями для игроков с низкой энергией")]
    public class EnergySystem : RustPlugin
    {
        private Dictionary<ulong, PlayerEnergyData> playerData = new Dictionary<ulong, PlayerEnergyData>();
        private Dictionary<ulong, string> uiPool = new Dictionary<ulong, string>();
        private List<MonumentData> monuments = new List<MonumentData>();
        private const float MAX_ENERGY = 200000f;
        private const float INITIAL_ENERGY = 30000f;
        private const float SAFE_ZONE_REGEN = 500f;    // Регенерация в безопасной зоне
        private const float NORMAL_ZONE_DRAIN = 50f;   // Расход в обычной зоне
        private const float RT_ZONE_DRAIN = 200f;      // Расход в RT зоне
        private const float DRAIN_INTERVAL = 10f;      // Интервал расхода энергии
        private const float REGEN_INTERVAL = 60f;      // Интервал регенерации
        private const float MOVEMENT_THRESHOLD = 20f;  // Проверка зоны при перемещении
        private const float DATA_SAVE_INTERVAL = 600f; // Сохранение данных раз в 10 минут
        private const float SIGNIFICANT_ENERGY_CHANGE = 100f; // Порог для обновления UI
        private const float ZONE_CHECK_INTERVAL = 1f;  // Интервал проверки зоны (1 секунда)

        // API Dictionary
        private static EnergySystem _instance;

        #region Data Structures
        private class PlayerEnergyData
        {
            public float Energy { get; set; }
            public Vector3 LastPosition { get; set; }
            public ZoneType CurrentZone { get; set; }
            public string UiId { get; set; }
            public long LastLogoutTime { get; set; }
            public bool IsDead { get; set; }
        }

        private class MonumentData
        {
            public string Name { get; set; }
            public Vector3 Position { get; set; }
            public float Radius { get; set; }
            public ZoneType Type { get; set; }
        }

        private enum ZoneType
        {
            Safe,    // Безопасная зона (шкаф, Outpost, Bandit Camp)
            Normal,  // Обычная зона
            RT       // RT зона (радтаун)
        }
        #endregion

        #region Data Management
        private void SaveData()
        {
            var dataToSave = playerData.ToDictionary(
                kvp => kvp.Key,
                kvp => new
                {
                    Energy = kvp.Value.Energy,
                    LastLogoutTime = kvp.Value.LastLogoutTime,
                    CurrentZone = kvp.Value.CurrentZone,
                    IsDead = kvp.Value.IsDead
                }
            );
            Interface.Oxide.DataFileSystem.WriteObject("EnergySystem", dataToSave);
        }

        private void LoadData()
        {
            var loadedData = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, Dictionary<string, object>>>("EnergySystem");
            foreach (var entry in loadedData)
            {
                playerData[entry.Key] = new PlayerEnergyData
                {
                    Energy = Convert.ToSingle(entry.Value["Energy"]),
                    LastPosition = Vector3.zero,
                    CurrentZone = entry.Value.ContainsKey("CurrentZone") ? (ZoneType)Enum.Parse(typeof(ZoneType), entry.Value["CurrentZone"].ToString()) : ZoneType.Normal,
                    UiId = null,
                    LastLogoutTime = entry.Value.ContainsKey("LastLogoutTime") ? Convert.ToInt64(entry.Value["LastLogoutTime"]) : 0,
                    IsDead = entry.Value.ContainsKey("IsDead") && Convert.ToBoolean(entry.Value["IsDead"])
                };
            }
        }
        #endregion

        #region Plugin Hooks
        private void Init()
        {
            LoadData();
            timer.Every(DRAIN_INTERVAL, DrainEnergyForAllPlayers);
            timer.Every(REGEN_INTERVAL, RegenEnergyForAllPlayers);
            timer.Every(DATA_SAVE_INTERVAL, SaveData);
            
            // Проверка зоны каждую секунду для всех игроков
            timer.Every(ZONE_CHECK_INTERVAL, CheckAllPlayerZones);
            
            // Регистрируем разрешение для команды energy_set
            permission.RegisterPermission("energysystem.admin", this);
            
            // Сохраняем экземпляр плагина для API доступа
            _instance = this;
        }

        private void OnServerInitialized()
        {
            CacheMonuments();
        }

        private void Unload()
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                DestroyUI(player);
            }
            uiPool.Clear();
            SaveData();
        }

        private void OnServerSave()
        {
            SaveData();
        }

        private void OnPlayerConnected(BasePlayer player)
        {
            if (!playerData.ContainsKey(player.userID))
            {
                playerData[player.userID] = new PlayerEnergyData
                {
                    Energy = INITIAL_ENERGY,
                    LastPosition = player.transform.position,
                    CurrentZone = GetPlayerZone(player, player.transform.position),
                    UiId = null,
                    LastLogoutTime = 0,
                    IsDead = false
                };
            }
            else
            {
                var data = playerData[player.userID];
                long currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
                if (data.LastLogoutTime > 0)
                {
                    float offlineSeconds = currentTime - data.LastLogoutTime;
                    float energyChange = CalculateOfflineEnergyChange(data.CurrentZone, data.IsDead, offlineSeconds);
                    data.Energy = Mathf.Clamp(data.Energy + energyChange, 0, MAX_ENERGY);
                }
                if (!data.IsDead)
                {
                    // Сразу определяем зону игрока при подключении
                    data.CurrentZone = GetPlayerZone(player, player.transform.position);
                }
            }
            playerData[player.userID].LastPosition = player.transform.position;
            
            // Создаем UI сразу после подключения
            timer.Once(0.1f, () => UpdateUI(player));
        }

        private void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            if (playerData.ContainsKey(player.userID))
            {
                playerData[player.userID].LastLogoutTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            }
            DestroyUI(player);
        }

        private void OnPlayerDie(BasePlayer player, HitInfo info)
        {
            if (playerData.ContainsKey(player.userID))
            {
                playerData[player.userID].IsDead = true;
                UpdateUI(player);
            }
        }

        private void OnPlayerRespawned(BasePlayer player)
        {
            if (playerData.ContainsKey(player.userID))
            {
                var data = playerData[player.userID];
                data.IsDead = false;
                data.CurrentZone = GetPlayerZone(player, player.transform.position);
                data.LastPosition = player.transform.position;
                
                // Восстанавливаем UI после респавна
                timer.Once(0.1f, () => UpdateUI(player));
            }
        }

        // Проверяет зоны для всех игроков
        private void CheckAllPlayerZones()
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player == null || !player.IsConnected || !playerData.ContainsKey(player.userID) || playerData[player.userID].IsDead)
                    continue;
                    
                var data = playerData[player.userID];
                Vector3 currentPosition = player.transform.position;
                
                // Снижен порог для более частой проверки
                if (Vector3.Distance(currentPosition, data.LastPosition) > 3f)
                {
                    CheckAndUpdatePlayerZone(player, currentPosition);
                }
            }
        }
        
        // Проверяет зону игрока и обновляет её при изменении
        private void CheckAndUpdatePlayerZone(BasePlayer player, Vector3 position)
        {
            if (!playerData.ContainsKey(player.userID)) return;
            
            var data = playerData[player.userID];
            ZoneType newZone = GetPlayerZone(player, position);
            
            if (newZone != data.CurrentZone)
            {
                string oldZoneName = data.CurrentZone.ToString();
                data.CurrentZone = newZone;
                data.LastPosition = position;
                
                string newZoneName = newZone.ToString();
                Puts($"Игрок {player.displayName} сменил зону с {oldZoneName} на {newZoneName}");
                
                // Отправляем сообщение игроку о смене зоны
                switch (newZone)
                {
                    case ZoneType.Safe:
                        SendReply(player, "Вы вошли в безопасную зону.Энергия восстанавливается.");
                        break;
                    case ZoneType.RT:
                        SendReply(player, "Вы вошли в радиоактивную зону.Энергия расходуется быстрее!");
                        break;
                    case ZoneType.Normal:
                        SendReply(player, "Вы вошли в обычную зону.");
                        break;
                }
                
                // Мгновенно обновляем UI для отражения смены зоны
                UpdateUI(player);
            }
            
            // В любом случае обновляем последнюю позицию
            data.LastPosition = position;
        }
        
        // Основной хук для обработки предметов в руках
        private void OnPlayerInput(BasePlayer player, InputState input)
        {
            if (input.IsDown(BUTTON.FORWARD) || input.IsDown(BUTTON.BACKWARD) || 
                input.IsDown(BUTTON.LEFT) || input.IsDown(BUTTON.RIGHT) ||
                input.IsDown(BUTTON.JUMP) || input.IsDown(BUTTON.DUCK))
            {
                var position = player.transform.position;
                CheckAndUpdatePlayerZone(player, position);
            }
        }
        
        // Отслеживание изменения энергии
        private void CheckEnergyForHoldingItems()
        {
            // Можно добавить логику проверки энергии для удержания предметов
        }

        private void ProcessPlayerDrain(BasePlayer player)
        {
            if (player == null || !player.IsConnected || !playerData.ContainsKey(player.userID) || playerData[player.userID].IsDead) return;
            
            var data = playerData[player.userID];
            
            // Проверяем зону игрока перед тратой энергии
            CheckAndUpdatePlayerZone(player, player.transform.position);
            
            if (data.CurrentZone != ZoneType.Safe) // Не тратим энергию в сейф-зонах
            {
                float energyChange = data.CurrentZone == ZoneType.RT ? -RT_ZONE_DRAIN : -NORMAL_ZONE_DRAIN;
                data.Energy = Mathf.Clamp(data.Energy + energyChange, 0, MAX_ENERGY);
                UpdateUI(player);
            }
        }

        // Наблюдение за изменением энергии при регенерации
        private void ProcessPlayerRegen(BasePlayer player)
        {
            if (player == null || !player.IsConnected || !playerData.ContainsKey(player.userID) || playerData[player.userID].IsDead) return;

            var data = playerData[player.userID];
            
            // Проверяем зону игрока перед регенерацией энергии
            CheckAndUpdatePlayerZone(player, player.transform.position);
            
            if (data.CurrentZone == ZoneType.Safe)
            {
                data.Energy = Mathf.Clamp(data.Energy + SAFE_ZONE_REGEN, 0, MAX_ENERGY);
                UpdateUI(player);
                Puts($"Регенерация энергии для {player.displayName}: +{SAFE_ZONE_REGEN}, текущая энергия: {data.Energy}");
            }
        }

        private float CalculateOfflineEnergyChange(ZoneType zone, bool isDead, float offlineSeconds)
        {
            if (isDead) return 0;
            return zone switch
            {
                ZoneType.Safe => SAFE_ZONE_REGEN * (offlineSeconds / REGEN_INTERVAL),
                ZoneType.RT => -RT_ZONE_DRAIN * (offlineSeconds / DRAIN_INTERVAL),
                _ => -NORMAL_ZONE_DRAIN * (offlineSeconds / DRAIN_INTERVAL)
            };
        }

        // Метод проверки и обновления для массовой обработки игроков
        private void DrainEnergyForAllPlayers()
        {
            var players = BasePlayer.activePlayerList.ToList();
            for (int i = 0; i < players.Count; i += 50)
            {
                int startIndex = i;
                timer.In(0.01f * (i / 50), () =>
                {
                    for (int j = startIndex; j < Math.Min(startIndex + 50, players.Count); j++)
                    {
                        ProcessPlayerDrain(players[j]);
                    }
                });
            }
        }

        private void RegenEnergyForAllPlayers()
        {
            var players = BasePlayer.activePlayerList.ToList();
            for (int i = 0; i < players.Count; i += 50)
            {
                int startIndex = i;
                timer.In(0.01f * (i / 50), () =>
                {
                    for (int j = startIndex; j < Math.Min(startIndex + 50, players.Count); j++)
                    {
                        ProcessPlayerRegen(players[j]);
                    }
                });
            }
        }
        #endregion

        #region UI Management
        private void UpdateUI(BasePlayer player)
        {
            if (!playerData.ContainsKey(player.userID)) return;
            var data = playerData[player.userID];

            // Удаляем старую панель, если есть
            if (!string.IsNullOrEmpty(data.UiId))
        {
                CuiHelper.DestroyUi(player, data.UiId);
                data.UiId = null;
                uiPool.Remove(player.userID);
            }

            // Создаем новую панель
            var elements = new CuiElementContainer();
            string panelId = elements.Add(new CuiPanel
            {
                Image = { Color = "0 0 0 0.5" },
                RectTransform = { AnchorMin = "0.02 0.85", AnchorMax = "0.25 0.90" },
                CursorEnabled = false
            }, "Hud", "EnergySystemPanel");
            data.UiId = panelId;
            uiPool[player.userID] = panelId;

            string barColor = data.CurrentZone switch
            {
                ZoneType.Safe => "0.2 0.8 0.2 1",  // Зеленый
                ZoneType.Normal => "0.8 0.8 0.2 1", // Желтый
                ZoneType.RT => "0.8 0.2 0.2 1",     // Красный
                _ => "0.8 0.8 0.2 1"
            };

            float energyFraction = data.Energy / MAX_ENERGY;

            // Добавляем полоску энергии
            elements.Add(new CuiElement
            {
                Name = CuiHelper.GetGuid(),
                Parent = panelId,
                Components =
                {
                    new CuiImageComponent { Color = barColor },
                    new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = $"{energyFraction} 0.5" }
                }
            });

            // Добавляем текст
            elements.Add(new CuiLabel
            {
                Text = { Text = $"Energy: {data.Energy:F0}/{MAX_ENERGY}", FontSize = 12, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" },
                RectTransform = { AnchorMin = "0 0.5", AnchorMax = "1 1" }
            }, panelId);

            CuiHelper.AddUi(player, elements);
        }
        
        private void DestroyUI(BasePlayer player)
        {
            if (!playerData.ContainsKey(player.userID)) return;
            var data = playerData[player.userID];
            if (!string.IsNullOrEmpty(data.UiId))
        {
                CuiHelper.DestroyUi(player, data.UiId);
                data.UiId = null;
                uiPool.Remove(player.userID);
            }
        }
        #endregion

        #region Commands
        [ChatCommand("energy")]
        private void CheckEnergy(BasePlayer player, string command, string[] args)
        {
            if (!playerData.ContainsKey(player.userID)) return;
            var data = playerData[player.userID];
            SendReply(player, $"Ваша энергия: {data.Energy:F0}/{MAX_ENERGY}");
            UpdateUI(player);
        }
        
        [ChatCommand("energy_set")]
        private void SetPlayerEnergy(BasePlayer player, string command, string[] args)
        {
            if (!player.IsAdmin && !permission.UserHasPermission(player.UserIDString, "energysystem.admin"))
            {
                SendReply(player, "У вас нет прав для выполнения этой команды!");
                return;
            }
            
            if (args.Length != 2)
            {
                SendReply(player, "Использование: /energy_set <steamID или ник> <количество_энергии>");
                return;
            }
            
            string targetIdentifier = args[0];
            BasePlayer targetPlayer = null;
            ulong targetSteamID = 0;
            
            if (ulong.TryParse(targetIdentifier, out targetSteamID))
            {
                targetPlayer = BasePlayer.FindByID(targetSteamID);
            }
            else
            {
                targetPlayer = BasePlayer.Find(targetIdentifier);
                if (targetPlayer != null)
                {
                    targetSteamID = targetPlayer.userID;
                }
                else
                {
                    SendReply(player, "Игрок не найден! Проверьте SteamID или никнейм.");
                    return;
                }
            }
            
            if (!float.TryParse(args[1], out float energyAmount))
            {
                SendReply(player, "Некорректное количество энергии!");
                return;
            }
            
            if (!playerData.ContainsKey(targetSteamID))
            {
                playerData[targetSteamID] = new PlayerEnergyData
                {
                    Energy = INITIAL_ENERGY,
                    LastPosition = Vector3.zero,
                    CurrentZone = ZoneType.Normal,
                    UiId = null,
                    LastLogoutTime = 0,
                    IsDead = false
                };
            }
            
            playerData[targetSteamID].Energy = Mathf.Clamp(energyAmount, 0, MAX_ENERGY);
            
            if (targetPlayer != null && targetPlayer.IsConnected)
            {
                UpdateUI(targetPlayer);
                SendReply(targetPlayer, $"Администратор {player.displayName} установил вам энергию: {energyAmount:F0}");
            }
            
            SendReply(player, $"Вы установили игроку {(targetPlayer != null ? targetPlayer.displayName : targetSteamID.ToString())} энергию: {energyAmount:F0}");
            SaveData(); 
        }
        #endregion

        #region Helper Methods
        private void CacheMonuments()
        {
            monuments.Clear();
            if (TerrainMeta.Path == null || TerrainMeta.Path.Monuments == null)
            {
                timer.Once(5f, CacheMonuments);
                return;
            }

            Puts("Начинаю кэширование монументов...");
            
            string[] rtKeywords = new string[] {
                "radtown", "launch_site", "powerplant", "trainyard", "military_tunnel", "airfield", 
                "water_treatment", "harbor", "arctic", "research", "dome", "satellite", "junkyard",
                "excavator", "sewer", "abandoned", "giant", "supermarket", "gas", "station",
                "lighthouse", "cave", "warehouse", "mining", "quarry", "mining_quarry", "arctic_research_base"
            };
            
            string[] safeKeywords = new string[] {
                "outpost", "bandit", "ranch", "barn", "compound", "fishing_village", "safe"
            };

            Dictionary<string, float> monumentRadiusMap = new Dictionary<string, float>
            {
                {"lighthouse/lighthouse.prefab", 40f},
                {"launch_site.prefab", 200f},
                {"military_tunnel.prefab", 180f},
                {"powerplant.prefab", 180f},
                {"airfield.prefab", 170f},
                {"water_treatment.prefab", 170f},
                {"harbor.prefab", 100f},
                {"harbor_2.prefab", 100f},
                {"trainyard.prefab", 100f},
                {"dome.prefab", 80f},
                {"junkyard.prefab", 80f},
                {"satellite_dish.prefab", 80f},
                {"arctic_research_base.prefab", 80f},
                {"gas_station.prefab", 60f},
                {"supermarket.prefab", 60f},
                
                {"bandit_town.prefab", 160f},
                {"compound.prefab", 160f},
                
                {"cave_small_medium.prefab", 50f},
                {"cave_medium_medium.prefab", 50f},
                {"cave_small_easy.prefab", 50f},
                {"cave_small_hard.prefab", 50f},
                {"cave_large_medium.prefab", 50f},
                
                {"fishing_village.prefab", 80f},
                {"fishing_village_small.prefab", 80f},
                {"underwater_lab_a.prefab", 100f},
                {"underwater_lab_b.prefab", 100f},
                {"underwater_lab_c.prefab", 100f},
                {"underwater_lab_d.prefab", 100f},
                {"oilrig_1.prefab", 100f},
                {"oilrig_2.prefab", 100f}
            };

            foreach (var monument in TerrainMeta.Path.Monuments)
            {
                if (monument == null) continue;
                
                string fullName = monument.name;
                string lowerName = fullName.ToLower();
                ZoneType type = ZoneType.Normal;
                
                string fileName = lowerName.Contains("/") 
                    ? lowerName.Substring(lowerName.LastIndexOf("/") + 1) 
                    : lowerName;
                    
                Puts($"Обрабатываю монумент: {fullName}, файл: {fileName}");
                
                foreach(var keyword in rtKeywords)
                {
                    if (lowerName.Contains(keyword))
                    {
                        type = ZoneType.RT;
                        break;
                    }
                }
                
                if (type != ZoneType.RT)
                {
                    foreach(var keyword in safeKeywords)
                    {
                        if (lowerName.Contains(keyword))
                        {
                            if (lowerName.Contains("fishing_village") && !lowerName.Contains("bandit") && !lowerName.Contains("outpost"))
                            {
                                type = ZoneType.Normal;
                            }
                            else
                            {
                                type = ZoneType.Safe;
                            }
                            break;
                        }
                    }
                }
                
                float radius = 100f; 
                
                foreach (var entry in monumentRadiusMap)
                {
                    if (fileName.EndsWith(entry.Key))
                    {
                        radius = entry.Value;
                        Puts($"Установлен специальный радиус для {fileName}: {radius}");
                        break;
                    }
                }
                
                if (radius == 100f)
                {
                    if (type == ZoneType.RT)
                        radius = 80f;
                    else if (type == ZoneType.Safe)
                        radius = 150f;
                    else
                        radius = 100f;
                }
                
                monuments.Add(new MonumentData
                {
                    Name = monument.name,
                    Position = monument.transform.position,
                    Radius = radius,
                    Type = type
                });
                
                Puts($"Добавлен монумент: {monument.name}, Тип: {type}, Радиус: {radius}");
            }
            
            Puts($"Кэшировано {monuments.Count} монументов");
        }

        private ZoneType GetPlayerZone(BasePlayer player, Vector3 position)
        {
            var privilege = player.GetBuildingPrivilege();
            if (privilege != null && privilege.IsAuthed(player))
            {
                return ZoneType.Safe;
            }

            foreach (var monument in monuments)
            {
                float distance = Vector3.Distance(position, monument.Position);
                if (distance < monument.Radius)
                {
                    return monument.Type;
                }
            }

            if (player.InSafeZone())
            {
                return ZoneType.Safe;
            }

            return ZoneType.Normal;
        }
        #endregion

        #region API Methods
        private float GetPlayerEnergy(ulong playerId)
        {
            if (playerData.ContainsKey(playerId))
                return playerData[playerId].Energy;
            return 0f;
        }
        
        private void SetPlayerEnergy(ulong playerId, float amount)
        {
            if (!playerData.ContainsKey(playerId))
            {
                playerData[playerId] = new PlayerEnergyData
                {
                    Energy = Mathf.Clamp(amount, 0, MAX_ENERGY),
                    LastPosition = Vector3.zero,
                    CurrentZone = ZoneType.Normal,
                    UiId = null,
                    LastLogoutTime = 0,
                    IsDead = false
                };
            }
            else
            {
                playerData[playerId].Energy = Mathf.Clamp(amount, 0, MAX_ENERGY);
            }
            
            var player = BasePlayer.FindByID(playerId);
            if (player != null && player.IsConnected)
            {
                UpdateUI(player);
            }
        }
        
        private void ModifyPlayerEnergy(ulong playerId, float amount)
        {
            if (!playerData.ContainsKey(playerId))
            {
                playerData[playerId] = new PlayerEnergyData
                {
                    Energy = Mathf.Clamp(INITIAL_ENERGY + amount, 0, MAX_ENERGY),
                    LastPosition = Vector3.zero,
                    CurrentZone = ZoneType.Normal,
                    UiId = null,
                    LastLogoutTime = 0,
                    IsDead = false
                };
            }
            else
            {
                playerData[playerId].Energy = Mathf.Clamp(playerData[playerId].Energy + amount, 0, MAX_ENERGY);
            }
            
            var player = BasePlayer.FindByID(playerId);
            if (player != null && player.IsConnected)
            {
                UpdateUI(player);
            }
        }
        
        private float GetMaxEnergy()
        {
            return MAX_ENERGY;
        }
        
        private ZoneType GetCurrentPlayerZone(ulong playerId)
        {
            if (playerData.ContainsKey(playerId))
                return playerData[playerId].CurrentZone;
            return ZoneType.Normal;
        }
        
        private void CallHook_OnEnergyChanged(ulong playerId, float oldEnergy, float newEnergy)
        {
            Interface.CallHook("OnPlayerEnergyChanged", playerId, oldEnergy, newEnergy);
        }
        
        private void CallHook_OnZoneChanged(ulong playerId, ZoneType oldZone, ZoneType newZone)
        {
            Interface.CallHook("OnPlayerZoneChanged", playerId, oldZone.ToString(), newZone.ToString());
        }
        
        public static class API
        {
            public static float GetPlayerEnergy(ulong playerId)
            {
                return _instance?.GetPlayerEnergy(playerId) ?? 0f;
            }
            
            public static void SetPlayerEnergy(ulong playerId, float amount)
            {
                _instance?.SetPlayerEnergy(playerId, amount);
            }
            
            public static void ModifyPlayerEnergy(ulong playerId, float amount)
            {
                _instance?.ModifyPlayerEnergy(playerId, amount);
            }
            
            public static float GetMaxEnergy()
            {
                return _instance?.GetMaxEnergy() ?? 0f;
            }
            
            public static string GetPlayerZone(ulong playerId)
            {
                return _instance?.GetCurrentPlayerZone(playerId).ToString() ?? "Unknown";
            }
        }
        #endregion
    }
}

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