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

FREE FuelStatus : 0.1.3 0.1.3

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
/*
*  < ----- End-User License Agreement ----->
*  
*  You may not copy, modify, merge, publish, distribute, sublicense, or sell copies of this software without the developer’s consent.*
*  THIS SOFTWARE IS PROVIDED BY IIIaKa AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
*  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
*  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*
*  Developer: IIIaKa
*      https://t.me/iiiaka
*      Discord: @iiiaka
*      https://github.com/IIIaKa
*      https://umod.org/user/IIIaKa
*      https://codefling.com/iiiaka
*      https://www.patreon.com/iiiaka
*      https://boosty.to/iiiaka
*  Codefling plugin page: https://codefling.com/plugins/fuel-status
*  Codefling license: https://codefling.com/plugins/fuel-status?tab=downloads_field_4
*
*  Copyright © 2024 IIIaKa
*/

using System;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using Oxide.Core;

namespace Oxide.Plugins
{
	[Info("Fuel Status", "IIIaKa", "0.1.3")]
	[Description("The plugin displays the vehicle's fuel level in the status bar.Depends on AdvancedStatus plugin.")]
	class FuelStatus : RustPlugin
	{
		[PluginReference]
		private Plugin ImageLibrary, AdvancedStatus;

		#region ~Variables~
		private bool _imgLibIsLoaded = false, _runEffect = false;
		private const string BarID = "FuelStatus_Fuel", ZeroLang = "MsgProgressZero", LowLang = "MsgFuelLow", StatusCreateBar = "CreateBar", StatusUpdateContent = "UpdateContent", StatusDeleteBar = "DeleteBar", Pedal = "pedal";
		private readonly string[] HttpScheme = new string[2] { "http://", "https://" };
		private (string Key, string Value) _barImage;
		private Hash<ulong, IFuelSystem> _fuels = new Hash<ulong, IFuelSystem>();
		private Hash<ulong, float> _prevLevel = new Hash<ulong, float>();
		private Timer _timer;
		private readonly int[] _driverSit = new int[] { 1, 5, 9, 11, 21, 23, 26, 28, 31 };
		private List<GaugeIndicator> _defaultIndicators = new List<GaugeIndicator>() { new GaugeIndicator(0.0f, 0.2f, "#F70000"), new GaugeIndicator(0.2f, 0.6f, "#F7BB00"), new GaugeIndicator(0.6f, 1.0f, "#B1C06E") };
		#endregion

		#region ~Configuration~
		private static Configuration _config;

		private class Configuration
		{
			[JsonProperty(PropertyName = "Fuel indicator refresh interval in seconds")]
			public float Fuel_Update_Time = 5f;
			
			[JsonProperty(PropertyName = "Notifications - The percentage(0.0 to 1.0) of fuel at which notifications will occur.A value of 0 disables this")]
            public float Notifications_Level = 0.2f;
			
			[JsonProperty(PropertyName = "Notifications - The effect that will be triggered upon a warning.Choose the effect carefully! An empty string disables the effect call")]
            public string Notifications_Effect = "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab";
			
			[JsonProperty(PropertyName = "Status.Bar - Height")]
			public int Status_Bar_Height = 26;

			[JsonProperty(PropertyName = "Status.Bar - Order")]
			public int Status_Bar_Order = 1;

			[JsonProperty(PropertyName = "Status.Background - Color")]
			public string Status_Background_Color = "#FFFFFF";
			
			[JsonProperty(PropertyName = "Status.Background - Transparency")]
			public float Status_Background_Transparency = 0.15f;
			
			[JsonProperty(PropertyName = "Status.Background - Material(empty to disable)")]
			public string Status_Background_Material = "";

			[JsonProperty(PropertyName = "Status.Image - Url")]
			public string Status_Image_Url = "https://i.imgur.com/LP54lLZ.png";
			
			[JsonProperty(PropertyName = "Status.Image - Local(Leave empty to use Image_Url)")]
            public string Status_Image_Local = "FuelStatus_Fuel";
			
			[JsonProperty(PropertyName = "Status.Image - Sprite(Leave empty to use Image_Local or Image_Url)")]
			public string Status_Image_Sprite = "";

			[JsonProperty(PropertyName = "Status.Image - Is raw image")]
			public bool Status_Image_IsRawImage = false;

			[JsonProperty(PropertyName = "Status.Image - Color")]
			public string Status_Image_Color = "#E2DBD6";
			
			[JsonProperty(PropertyName = "Status.Image - Transparency")]
			public float Status_Image_Transparency = 0.55f;
			
			[JsonProperty(PropertyName = "Status.Text - Size")]
			public int Status_Text_Size = 15;
			
			[JsonProperty(PropertyName = "Status.Text - Color")]
			public string Status_Text_Color = "#E2DBD6";

			[JsonProperty(PropertyName = "Status.Text - Font(https://umod.org/guides/rust/basic-concepts-of-gui#fonts)")]
			public string Status_Text_Font = "RobotoCondensed-Bold.ttf";
			
			[JsonProperty(PropertyName = "Status.Text - Offset Horizontal")]
			public int Status_Text_Offset_Horizontal = 7;
			
			[JsonProperty(PropertyName = "Status.Progress - Transparency")]
			public float Status_Progress_Transparency = 0.8f;
			
			[JsonProperty(PropertyName = "Status.Progress - OffsetMin")]
			public string Status_Progress_OffsetMin = "25 2.5";
			
			[JsonProperty(PropertyName = "Status.Progress - OffsetMax")]
			public string Status_Progress_OffsetMax = "-3.5 -3.5";
			
			[JsonProperty(PropertyName = "Status.Progress - Zero Text Size")]
			public int Status_Progress_Zero_Size = 12;
			
			[JsonProperty(PropertyName = "Status.Progress - Zero Text Color")]
			public string Status_Progress_Zero_Color = "#F70000";
			
			[JsonProperty(PropertyName = "List of Gauge Indicators")]
			public List<GaugeIndicator> GaugeIndicators = new List<GaugeIndicator>();

			public Oxide.Core.VersionNumber Version;
		}
		
		public class GaugeIndicator
        {
			private float _minRange;
			public float MinRange
			{
				get => _minRange;
				set => _minRange = Mathf.Clamp(value, 0f, 1f);
			}
			
			private float _maxRange;
			public float MaxRange
			{
				get => _maxRange;
				set => _maxRange = Mathf.Clamp(value, 0f, 1f);
			}
			
			public string Color { get; set; } = string.Empty;
			
			public GaugeIndicator() {}
			public GaugeIndicator(float min, float max, string color)
            {
				MinRange = min;
				MaxRange = max;
				Color = color;
			}
		}
		
		protected override void LoadConfig()
        {
            base.LoadConfig();
            try { _config = Config.ReadObject<Configuration>(); }
            catch (Exception ex) { PrintError($"{ex.Message}\n\n[{Title}] Your configuration file contains an error."); }
            if (_config == null || _config.Version == new VersionNumber())
            {
                PrintWarning("The configuration file is not found or contains errors.Creating a new one...");
                LoadDefaultConfig();
            }
            else if (_config.Version < Version)
            {
                PrintWarning($"Your configuration file version({_config.Version}) is outdated.Updating it to {Version}.");
                _config.Version = Version;
                PrintWarning($"The configuration file has been successfully updated to version {_config.Version}!");
            }
			
			_config.Notifications_Level = Mathf.Clamp(_config.Notifications_Level, 0f, 1f);
			if (!string.IsNullOrWhiteSpace(_config.Notifications_Effect))
				_runEffect = true;
			if (_config.GaugeIndicators == null || !_config.GaugeIndicators.Any())
				_config.GaugeIndicators = new List<GaugeIndicator>(_defaultIndicators);
			SaveConfig();
        }
		
		protected override void SaveConfig() => Config.WriteObject(_config);
		protected override void LoadDefaultConfig() => _config = new Configuration() { Version = Version };
		#endregion
		
		#region ~Language~
		protected override void LoadDefaultMessages()
		{
			lang.RegisterMessages(new Dictionary<string, string>
			{
				["MsgProgressZero"] = "Out of fuel, refill required!",
				["MsgFuelLow"] = "Warning: Fuel level is low!"
            }, this);
			lang.RegisterMessages(new Dictionary<string, string>
			{
				["MsgProgressZero"] = "Нет топлива!",
				["MsgFuelLow"] = "Внимание: уровень топлива низкий!"
            }, this, "ru");
		}
		#endregion
		
		#region ~Methods~
		private void LoadImages()
		{
			if (_imgLibIsLoaded && string.IsNullOrWhiteSpace(_config.Status_Image_Local) && _config.Status_Image_Url.StartsWithAny(HttpScheme))
				ImageLibrary?.Call("AddImage", _config.Status_Image_Url, BarID, 0uL);
		}
		
		private void InitPlugin()
        {
			if (!string.IsNullOrEmpty(_config.Status_Image_Local))
				AdvancedStatus?.Call("LoadImage", BarID);
			InitSelectedImage();
			foreach (var player in BasePlayer.activePlayerList)
            {
				if (!player.IsNpc && TryGetFuel(player, out var fuelSystem))
					SendBar(player.userID, fuelSystem);
			}
            Subscribe(nameof(OnEntityMounted));
            Subscribe(nameof(OnEntityDismounted));
            Subscribe(nameof(OnEntityKill));
            _timer = timer.Every(_config.Fuel_Update_Time, () => { UpdateFuel(); });
        }
		
		private void SendBar(ulong userID, IFuelSystem fuelSystem)
        {
			if (fuelSystem == null) return;
			float progress = fuelSystem.GetFuelFraction();
			Dictionary<string, object> parameters = new Dictionary<string, object>
			{
				{ "Id", BarID },
				{ "Plugin", Name },
				{ "Order", _config.Status_Bar_Order },
				{ "Height", _config.Status_Bar_Height },
				{ "Main_Color", _config.Status_Background_Color },
				{ "Main_Transparency", _config.Status_Background_Transparency },
				{ "Main_Material", _config.Status_Background_Material },
				{ _barImage.Key, _barImage.Value },
				{ "Is_RawImage", _config.Status_Image_IsRawImage },
				{ "Image_Color", _config.Status_Image_Color },
				{ "Image_Transparency", _config.Status_Image_Transparency },
				{ "Text_Font", _config.Status_Text_Font },
				{ "Text_Offset_Horizontal", _config.Status_Text_Offset_Horizontal },
				{ "Progress", progress }
			};
			if (progress > 0f)
			{
				parameters.Add("Text", fuelSystem.GetFuelAmount().ToString());
				parameters.Add("Text_Size", _config.Status_Text_Size);
				parameters.Add("Text_Color", _config.Status_Text_Color);
				parameters.Add("Progress_Color", GetProgressColor(progress));
				parameters.Add("Progress_Transparency", _config.Status_Progress_Transparency);
				parameters.Add("Progress_OffsetMin", _config.Status_Progress_OffsetMin);
				parameters.Add("Progress_OffsetMax", _config.Status_Progress_OffsetMax);
			}
			else
			{
				parameters.Add("Text", lang.GetMessage(ZeroLang, this, userID.ToString()));
				parameters.Add("Text_Size", _config.Status_Progress_Zero_Size);
				parameters.Add("Text_Color", _config.Status_Progress_Zero_Color);
			}
			AdvancedStatus?.Call(StatusCreateBar, userID, parameters);
			_fuels[userID] = fuelSystem;
		}
		
		private void UpdateFuelValue(ulong userID, IFuelSystem fuelSystem)
        {
			if (fuelSystem == null) return;
			string userIDString = userID.ToString();
			float progress = fuelSystem.GetFuelFraction();
			Dictionary<string, object> parameters = new Dictionary<string, object>
			{
				{ "Id", BarID },
				{ "Plugin", Name },
				{ "Progress", progress }
			};
			if (progress > 0f)
			{
				parameters.Add("Text", fuelSystem.GetFuelAmount().ToString());
				parameters.Add("Text_Size", _config.Status_Text_Size);
				parameters.Add("Text_Color", _config.Status_Text_Color);
				parameters.Add("Progress_Color", GetProgressColor(progress));
				parameters.Add("Progress_Transparency", _config.Status_Progress_Transparency);
				parameters.Add("Progress_OffsetMin", _config.Status_Progress_OffsetMin);
				parameters.Add("Progress_OffsetMax", _config.Status_Progress_OffsetMax);
			}
			else
			{
				parameters.Add("Text", lang.GetMessage(ZeroLang, this, userIDString));
				parameters.Add("Text_Size", _config.Status_Progress_Zero_Size);
				parameters.Add("Text_Color", _config.Status_Progress_Zero_Color);
			}
			AdvancedStatus?.Call(StatusUpdateContent, userID, parameters);

			if (_config.Notifications_Level <= 0f) return;
			if (progress <= _config.Notifications_Level && _prevLevel.TryGetValue(userID, out var oldLevel) && oldLevel > _config.Notifications_Level)
            {
                var player = BasePlayer.FindByID(userID);
                if (player != null)
                {
                    player.Command("gametip.showtoast", (int)GameTip.Styles.Error, lang.GetMessage(LowLang, this, userIDString), string.Empty);
                    if (_runEffect)
                        Effect.server.Run(_config.Notifications_Effect, player, 0u, Vector3.zero, Vector3.zero);
                }
            }
            _prevLevel[userID] = progress;
		}
		
		private void DestroyBar(ulong userID)
        {
			if (_fuels.ContainsKey(userID))
            {
				_fuels.Remove(userID);
				_prevLevel.Remove(userID);
				AdvancedStatus?.Call(StatusDeleteBar, userID, BarID, Name);
			}
		}
		
		private void InitSelectedImage()
        {
			if (!string.IsNullOrEmpty(_config.Status_Image_Sprite))
				_barImage = ("Image_Sprite", _config.Status_Image_Sprite);
			else if (!string.IsNullOrEmpty(_config.Status_Image_Local))
				_barImage = ("Image_Local", _config.Status_Image_Local);
			else
				_barImage = ("Image", _imgLibIsLoaded && _config.Status_Image_Url.StartsWithAny(HttpScheme) ? BarID : _config.Status_Image_Url);
		}
		
		private string GetProgressColor(float progress)
        {
			foreach (var indicator in _config.GaugeIndicators)
			{
				if (progress >= indicator.MinRange && progress <= indicator.MaxRange)
					return indicator.Color;
			}
			Puts($"Could not find a color for the value {progress}f.Default color will be used.");
			return "#B1C06E";
		}
		
		private bool TryGetFuel(BasePlayer player, out IFuelSystem result)
        {
			result = null;
			if (!player.isMounted)
				return false;
			var mount = player.GetMounted();
			if (mount.IsValid() && mount.isMobile && _driverSit.Contains((int)mount.mountPose))
			{
				var vehicle = mount.VehicleParent();
				if (vehicle != null && !vehicle.ShortPrefabName.Contains(Pedal))
					result = vehicle.GetFuelSystem();
			}
			return result != null;
		}
		
		private void UpdateFuel()
        {
			foreach (var kvp in _fuels)
			{
				if (kvp.Value != null)
					UpdateFuelValue(kvp.Key, kvp.Value);
			}
		}
		#endregion

        #region ~Oxide Hooks~
        void OnEntityMounted(BaseMountable mount, BasePlayer player)
        {
			if (TryGetFuel(player, out var fuelSystem))
				SendBar(player.userID, fuelSystem);
		}
		
		void OnEntityMounted(DiverPropulsionVehicle dpv, BasePlayer player)
        {
			var fuelSystem = dpv.GetFuelSystem();
			if (fuelSystem != null)
				SendBar(player.userID, fuelSystem);
		}
		
		void OnEntityDismounted(BaseMountable mount, BasePlayer player) => DestroyBar(player.userID);
		
		void OnEntityKill(BaseVehicle vehicle)
        {
			var driver = vehicle.GetDriver();
			if (driver != null)
				DestroyBar(driver.userID);
		}
		
		void OnEntityKill(DiverPropulsionVehicle dpv)
        {
			var driver = dpv.GetMounted();
			if (driver != null)
                DestroyBar(driver.userID);
        }
		
		void OnAdvancedStatusLoaded() => InitPlugin();
		
		void OnPluginLoaded(Plugin plugin)
		{
			if (plugin == ImageLibrary)
			{
				_imgLibIsLoaded = true;
				LoadImages();
				InitSelectedImage();
			}
		}
		
		void OnPluginUnloaded(Plugin plugin)
		{
			if (plugin.Name == "ImageLibrary")
				_imgLibIsLoaded = false;
			else if (plugin.Name == "AdvancedStatus")
			{
				Unsubscribe(nameof(OnEntityMounted));
				Unsubscribe(nameof(OnEntityDismounted));
				Unsubscribe(nameof(OnEntityKill));
				if (_timer != null)
					_timer.Destroy();
				_fuels.Clear();
				_prevLevel.Clear();
			}
		}

		void Init()
		{
			Unsubscribe(nameof(OnEntityMounted));
			Unsubscribe(nameof(OnEntityDismounted));
			Unsubscribe(nameof(OnEntityKill));
			Unsubscribe(nameof(OnAdvancedStatusLoaded));
		}

		void OnServerInitialized(bool initial)
        {
			_imgLibIsLoaded = ImageLibrary != null && ImageLibrary.IsLoaded;
			if (_imgLibIsLoaded)
				LoadImages();
			bool statusIsLoaded = AdvancedStatus != null && AdvancedStatus?.Call("IsReady") != null;
			if (!statusIsLoaded)
            {
				if (initial && AdvancedStatus != null)
                    PrintWarning("AdvancedStatus plugin found, but not ready yet.Waiting for it to load...");
                else
                    PrintWarning("AdvancedStatus plugin not found! To function, it is necessary to install it!\nhttps://codefling.com/plugins/advanced-status");
            }
			else
				OnAdvancedStatusLoaded();
			Subscribe(nameof(OnAdvancedStatusLoaded));
		}

		void Unload()
		{
			if (_timer != null)
				_timer.Destroy();
			_config = null;
		}
		#endregion
	}
}

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