Decompiled source of VioletShiftAlarm v0.1.0

BepInEx/plugins/VioletShiftAlarm.dll

Decompiled 2 days ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("VioletShiftAlarm")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("VioletShiftAlarm")]
[assembly: AssemblyTitle("VioletShiftAlarm")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace VioletMods.VioletShiftAlarm
{
	[BepInPlugin("com.violetmods.lethalcompany.violetshiftalarm", "Violet Shift Alarm", "0.1.0")]
	public sealed class VioletShiftAlarm : BaseUnityPlugin
	{
		public const string PluginGuid = "com.violetmods.lethalcompany.violetshiftalarm";

		public const string PluginName = "Violet Shift Alarm";

		public const string PluginVersion = "0.1.0";

		private ConfigEntry<bool> _showClock;

		private ConfigEntry<bool> _showWarnings;

		private ConfigEntry<bool> _showInShip;

		private ConfigEntry<float> _firstHour;

		private ConfigEntry<float> _secondHour;

		private ConfigEntry<float> _lastHour;

		private ConfigEntry<float> _warningDuration;

		private ConfigEntry<float> _horizontalOffset;

		private ConfigEntry<float> _verticalOffset;

		private ConfigEntry<KeyboardShortcut> _toggle;

		private bool _visible = true;

		private bool _hasGameClock;

		private float _displayHour;

		private float _previousHour = -1f;

		private float _scanDelay;

		private float _resolveDelay;

		private float _bannerLeft;

		private string _bannerTitle = "";

		private string _bannerSubtitle = "";

		private int _warningLevel;

		private Type _timeOfDayType;

		private Type _startOfRoundType;

		private Texture2D _solidPixel;

		private static readonly Color Purple = new Color(0.75f, 0.39f, 1f, 1f);

		private static readonly Color Amber = new Color(1f, 0.78f, 0.36f, 1f);

		private static readonly Color Red = new Color(1f, 0.32f, 0.48f, 1f);

		private void Awake()
		{
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			_showClock = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "ShowClock", true, "Show a small always-visible local clock on moon runs.");
			_showWarnings = ((BaseUnityPlugin)this).Config.Bind<bool>("Warnings", "Enabled", true, "Show temporary visual alerts when an in-game hour is crossed.");
			_showInShip = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "VisibleInsideShip", true, "Show the clock while inside the ship on a moon.");
			_firstHour = ((BaseUnityPlugin)this).Config.Bind<float>("Warnings", "FirstAlertHour24", 16f, "First alert (24-hour clock), default 16 = 4 PM.");
			_secondHour = ((BaseUnityPlugin)this).Config.Bind<float>("Warnings", "SecondAlertHour24", 19f, "Second alert (24-hour clock), default 19 = 7 PM.");
			_lastHour = ((BaseUnityPlugin)this).Config.Bind<float>("Warnings", "LastAlertHour24", 21f, "Final alert (24-hour clock), default 21 = 9 PM.");
			_warningDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Warnings", "DurationSeconds", 6f, "Duration for each visual warning, in real seconds.");
			_horizontalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "RightOffsetPixels", 24f, "Distance from the right screen edge.");
			_verticalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "TopOffsetPixels", 78f, "Distance from the top screen edge.");
			_toggle = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "ToggleHUD", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Toggle the entire overlay. Only affects your client.");
			_solidPixel = new Texture2D(1, 1, (TextureFormat)4, false);
			_solidPixel.SetPixel(0, 0, Color.white);
			_solidPixel.Apply();
			((Object)_solidPixel).hideFlags = (HideFlags)61;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Violet Shift Alarm loaded (client-side, visual only).");
		}

		private void Update()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = _toggle.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				_visible = !_visible;
			}
			if (_bannerLeft > 0f)
			{
				_bannerLeft = Mathf.Max(0f, _bannerLeft - Time.unscaledDeltaTime);
			}
			_scanDelay -= Time.unscaledDeltaTime;
			if (_scanDelay > 0f)
			{
				return;
			}
			_scanDelay = 0.15f;
			if (!TryReadCurrentHour(out var hour))
			{
				_hasGameClock = false;
				_previousHour = -1f;
				_bannerLeft = 0f;
				return;
			}
			_hasGameClock = true;
			_displayHour = hour;
			if (_previousHour >= 0f)
			{
				if (hour < _previousHour - 0.25f)
				{
					_previousHour = hour;
					_bannerLeft = 0f;
					return;
				}
				int num = 0;
				if (Crossed(_lastHour.Value, _previousHour, hour))
				{
					num = 3;
				}
				else if (Crossed(_secondHour.Value, _previousHour, hour))
				{
					num = 2;
				}
				else if (Crossed(_firstHour.Value, _previousHour, hour))
				{
					num = 1;
				}
				if (num > 0 && _showWarnings.Value)
				{
					TriggerAlert(num);
				}
			}
			_previousHour = hour;
		}

		private static bool Crossed(float threshold, float before, float after)
		{
			if (threshold >= 6f && threshold < 24f && before < threshold)
			{
				return after >= threshold;
			}
			return false;
		}

		private void TriggerAlert(int level)
		{
			_warningLevel = level;
			_bannerLeft = Mathf.Clamp(_warningDuration.Value, 1f, 30f);
			switch (level)
			{
			case 1:
				_bannerTitle = "CHECK YOUR ROUTE";
				_bannerSubtitle = "Afternoon shift - plan your return.";
				break;
			case 2:
				_bannerTitle = "TIME TO HEAD BACK";
				_bannerSubtitle = "It is getting late. Regroup with your crew.";
				break;
			default:
				_bannerTitle = "FINAL WARNING";
				_bannerSubtitle = "Night is closing in - return to the ship.";
				break;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Shift alert: " + _bannerTitle));
		}

		private bool TryReadCurrentHour(out float hour)
		{
			hour = 0f;
			try
			{
				if (_timeOfDayType == null || _startOfRoundType == null)
				{
					_resolveDelay -= 0.15f;
					if (_resolveDelay > 0f)
					{
						return false;
					}
					_resolveDelay = 3f;
					_timeOfDayType = FindGameType("TimeOfDay");
					_startOfRoundType = FindGameType("StartOfRound");
					if (_timeOfDayType == null || _startOfRoundType == null)
					{
						return false;
					}
				}
				object staticMember = GetStaticMember(_startOfRoundType, "Instance");
				object staticMember2 = GetStaticMember(_timeOfDayType, "Instance");
				if (!IsAlive(staticMember) || !IsAlive(staticMember2))
				{
					return false;
				}
				if (TryBool(staticMember, "inShipPhase", out var value) && value)
				{
					return false;
				}
				if (TryBool(staticMember, "shipIsLeaving", out var value2) && value2)
				{
					return false;
				}
				if (TryBool(staticMember2, "currentDayTimeStarted", out var value3) && !value3)
				{
					return false;
				}
				if (!_showInShip.Value)
				{
					Type type = FindGameType("GameNetworkManager");
					object obj = ((type == null) ? null : GetStaticMember(type, "Instance"));
					object obj2 = ((obj == null) ? null : GetMember(obj, "localPlayerController"));
					bool value4 = default(bool);
					if (obj2 != null && TryBool(obj2, "isInHangarShipRoom", out value4) && value4)
					{
						return false;
					}
				}
				if (!TryFloat(staticMember2, "normalizedTimeOfDay", out var value5))
				{
					return false;
				}
				float value6 = 18f;
				TryFloat(staticMember2, "numberOfHours", out value6);
				if (value6 < 1f || value6 > 24f)
				{
					value6 = 18f;
				}
				if (float.IsNaN(value5) || float.IsInfinity(value5))
				{
					return false;
				}
				hour = 6f + Mathf.Clamp(value5, 0f, 1f) * value6;
				return true;
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Clock unavailable: " + ex.GetType().Name));
				return false;
			}
		}

		private static bool IsAlive(object obj)
		{
			if (obj == null)
			{
				return false;
			}
			Object val = (Object)((obj is Object) ? obj : null);
			if (val != null && val == (Object)null)
			{
				return false;
			}
			return true;
		}

		private static Type FindGameType(string typeName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type = assemblies[i].GetType(typeName, throwOnError: false);
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}

		private static object GetStaticMember(Type type, string name)
		{
			FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				return field.GetValue(null);
			}
			PropertyInfo property = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(property == null))
			{
				return property.GetValue(null, null);
			}
			return null;
		}

		private static object GetMember(object instance, string name)
		{
			Type type = instance.GetType();
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				return field.GetValue(instance);
			}
			PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(property == null))
			{
				return property.GetValue(instance, null);
			}
			return null;
		}

		private static bool TryBool(object source, string member, out bool value)
		{
			value = false;
			if (!(GetMember(source, member) is bool flag))
			{
				return false;
			}
			value = flag;
			return true;
		}

		private static bool TryFloat(object source, string member, out float value)
		{
			value = 0f;
			object member2 = GetMember(source, member);
			if (member2 == null)
			{
				return false;
			}
			value = Convert.ToSingle(member2);
			return true;
		}

		private void OnGUI()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			if (_visible && _hasGameClock && !((Object)(object)_solidPixel == (Object)null) && (int)Event.current.type == 7)
			{
				float num = Mathf.Clamp(_horizontalOffset.Value, 0f, (float)Screen.width / 2f);
				float num2 = Mathf.Clamp(_verticalOffset.Value, 0f, (float)Screen.height / 2f);
				float num3 = Mathf.Max(0f, (float)Screen.width - 266f - num);
				if (_showClock.Value)
				{
					Rectangle(new Rect(num3, num2, 266f, 54f), new Color(0.06f, 0.05f, 0.11f, 0.79f));
					Rectangle(new Rect(num3, num2, 4f, 54f), Purple);
					Label(new Rect(num3 + 17f, num2 + 4f, 238f, 18f), "VIOLET SHIFT ALARM", 12, Purple, (FontStyle)1);
					Label(new Rect(num3 + 17f, num2 + 22f, 236f, 27f), FormatTime(_displayHour), 21, Color.white, (FontStyle)1);
				}
				if (_showWarnings.Value && _bannerLeft > 0f)
				{
					float num4 = num2 + (_showClock.Value ? 64f : 0f);
					Color val = ((_warningLevel == 3) ? Red : ((_warningLevel == 2) ? Amber : Purple));
					float num5 = ((_warningLevel == 3) ? (0.84f + 0.16f * Mathf.Sin(Time.unscaledTime * 8f)) : 1f);
					Rectangle(new Rect(num3, num4, 266f, 76f), new Color(0.06f, 0.05f, 0.11f, 0.88f));
					Rectangle(new Rect(num3, num4, 4f, 76f), val * num5);
					Label(new Rect(num3 + 16f, num4 + 7f, 242f, 28f), _bannerTitle, 16, val, (FontStyle)1);
					Label(new Rect(num3 + 16f, num4 + 35f, 239f, 36f), _bannerSubtitle, 12, Color.white, (FontStyle)0);
				}
			}
		}

		private static string FormatTime(float hour)
		{
			int num = Mathf.Clamp(Mathf.FloorToInt(hour * 60f), 0, 1439);
			int num2 = num / 60;
			int num3 = num % 60;
			int num4 = num2 % 12;
			if (num4 == 0)
			{
				num4 = 12;
			}
			return string.Format("{0}:{1:00} {2}", num4, num3, (num2 >= 12) ? "PM" : "AM");
		}

		private void Rectangle(Rect rect, Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			Color color2 = GUI.color;
			GUI.color = color;
			GUI.DrawTexture(rect, (Texture)(object)_solidPixel);
			GUI.color = color2;
		}

		private static void Label(Rect bounds, string message, int size, Color color, FontStyle style)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			GUIStyle val = new GUIStyle(GUI.skin.label)
			{
				fontSize = size,
				fontStyle = style,
				alignment = (TextAnchor)3,
				wordWrap = true
			};
			val.normal.textColor = color;
			GUIStyle val2 = val;
			GUI.Label(bounds, message, val2);
		}

		private void OnDestroy()
		{
			if ((Object)(object)_solidPixel != (Object)null)
			{
				Object.Destroy((Object)(object)_solidPixel);
			}
		}
	}
}