Decompiled source of CaptainDiabloTimer v0.1.4

plugins/CaptainDiabloTimer/CaptainDiabloTimer.dll

Decompiled 20 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using EntityStates;
using EntityStates.Captain.Weapon;
using Microsoft.CodeAnalysis;
using On.EntityStates;
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("CaptainDiabloTimer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CaptainDiabloTimer")]
[assembly: AssemblyTitle("CaptainDiabloTimer")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace CaptainDiabloTimer
{
	[BepInPlugin("com.trynlord.captain-diablo-timer", "Captain Diablo Timer", "0.1.4")]
	public sealed class CaptainDiabloTimerPlugin : BaseUnityPlugin
	{
		private sealed class StrikeTimer
		{
			public float EndTime;

			public int LastBeepSecond = int.MaxValue;
		}

		public const string PluginGuid = "com.trynlord.captain-diablo-timer";

		public const string PluginName = "Captain Diablo Timer";

		public const string PluginVersion = "0.1.4";

		private static CaptainDiabloTimerPlugin? _instance;

		private readonly List<StrikeTimer> _activeStrikes = new List<StrikeTimer>();

		private readonly List<float> _remainingTimes = new List<float>();

		private ConfigEntry<bool> _enabled;

		private ConfigEntry<float> _strikeDelaySeconds;

		private ConfigEntry<bool> _showCountdown;

		private ConfigEntry<bool> _showOnlyDuringWarning;

		private ConfigEntry<float> _warningStartsAtSeconds;

		private ConfigEntry<int> _maxVisibleTimers;

		private ConfigEntry<string> _labelText;

		private ConfigEntry<int> _fontSize;

		private ConfigEntry<float> _verticalPosition;

		private ConfigEntry<bool> _playBeeps;

		private ConfigEntry<bool> _playImpactBeep;

		private ConfigEntry<float> _beepVolume;

		private AudioSource? _audioSource;

		private AudioClip? _countdownBeep;

		private AudioClip? _impactBeep;

		private GUIStyle? _timerStyle;

		private void Awake()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			_instance = this;
			BindConfig();
			CreateAudio();
			AimThrowableBase.FireProjectile += new hook_FireProjectile(AimThrowableBase_FireProjectile);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Captain Diablo Timer 0.1.4 loaded (client-side only).");
		}

		private void OnDestroy()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			AimThrowableBase.FireProjectile -= new hook_FireProjectile(AimThrowableBase_FireProjectile);
			if ((Object)(object)_countdownBeep != (Object)null)
			{
				Object.Destroy((Object)(object)_countdownBeep);
			}
			if ((Object)(object)_impactBeep != (Object)null)
			{
				Object.Destroy((Object)(object)_impactBeep);
			}
			if ((Object)(object)_instance == (Object)(object)this)
			{
				_instance = null;
			}
		}

		private static void AimThrowableBase_FireProjectile(orig_FireProjectile orig, AimThrowableBase self)
		{
			orig.Invoke(self);
			try
			{
				if ((Object)(object)_instance != (Object)null && self is CallAirstrikeAlt)
				{
					((BaseUnityPlugin)_instance).Logger.LogInfo((object)"Diablo Strike confirmed; countdown started.");
					if (_instance._enabled.Value)
					{
						_instance.AddStrike();
					}
				}
			}
			catch (Exception arg)
			{
				CaptainDiabloTimerPlugin? instance = _instance;
				if (instance != null)
				{
					((BaseUnityPlugin)instance).Logger.LogError((object)$"Failed to start Diablo timer: {arg}");
				}
			}
		}

		private void BindConfig()
		{
			_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable the Diablo Strike countdown and warnings.");
			_strikeDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Timer", "StrikeDelaySeconds", 20f, "Seconds between confirming the Diablo Strike target and impact. Keep this at 20 for vanilla; change it only if another mod changes the delay.");
			_showCountdown = ((BaseUnityPlugin)this).Config.Bind<bool>("Timer", "ShowCountdown", true, "Show the on-screen countdown.");
			_showOnlyDuringWarning = ((BaseUnityPlugin)this).Config.Bind<bool>("Timer", "ShowOnlyDuringWarning", false, "Hide the timer until WarningStartsAtSeconds is reached.");
			_warningStartsAtSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Timer", "WarningStartsAtSeconds", 5f, "Timer turns red and countdown beeps begin at this many seconds.");
			_maxVisibleTimers = ((BaseUnityPlugin)this).Config.Bind<int>("Timer", "MaxVisibleTimers", 4, "Maximum simultaneous Diablo Strike timers shown on screen.");
			_labelText = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "Label", "DIABLO STRIKE", "Text shown before the remaining time.");
			_fontSize = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "FontSize", 34, "Countdown font size.");
			_verticalPosition = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "VerticalPosition", 0.16f, "Vertical screen position from 0 (top) to 1 (bottom).");
			_playBeeps = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "PlayCountdownBeeps", true, "Play one short beep per second during the warning window.");
			_playImpactBeep = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "PlayImpactBeep", true, "Play a lower double-length beep when the timer reaches zero.");
			_beepVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "BeepVolume", 0.55f, "Beep volume from 0 to 1.");
		}

		private void CreateAudio()
		{
			_audioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			_audioSource.playOnAwake = false;
			_audioSource.loop = false;
			_audioSource.spatialBlend = 0f;
			_countdownBeep = CreateTone("CaptainDiabloTimer_Countdown", 880f, 0.085f);
			_impactBeep = CreateTone("CaptainDiabloTimer_Impact", 440f, 0.17f);
		}

		private static AudioClip CreateTone(string name, float frequency, float duration)
		{
			int num = Mathf.Max(1, Mathf.CeilToInt(44100f * duration));
			float[] array = new float[num];
			for (int i = 0; i < num; i++)
			{
				float num2 = (float)i / 44100f;
				float num3 = Mathf.Sin(MathF.PI * (float)i / (float)num);
				array[i] = Mathf.Sin(MathF.PI * 2f * frequency * num2) * num3 * 0.35f;
			}
			AudioClip obj = AudioClip.Create(name, num, 1, 44100, false);
			obj.SetData(array, 0);
			return obj;
		}

		private void AddStrike()
		{
			float num = Mathf.Max(0.25f, _strikeDelaySeconds.Value);
			_activeStrikes.Add(new StrikeTimer
			{
				EndTime = Time.time + num
			});
			((BaseUnityPlugin)this).Logger.LogDebug((object)$"Local Diablo Strike timer started ({num:0.##}s).");
		}

		private void Update()
		{
			if (!_enabled.Value)
			{
				_activeStrikes.Clear();
				return;
			}
			int num = Mathf.Max(1, Mathf.CeilToInt(_warningStartsAtSeconds.Value));
			for (int num2 = _activeStrikes.Count - 1; num2 >= 0; num2--)
			{
				StrikeTimer strikeTimer = _activeStrikes[num2];
				float num3 = strikeTimer.EndTime - Time.time;
				if (num3 <= 0f)
				{
					if (_playImpactBeep.Value)
					{
						PlayClip(_impactBeep);
					}
					_activeStrikes.RemoveAt(num2);
				}
				else
				{
					int num4 = Mathf.CeilToInt(num3);
					if (_playBeeps.Value && num4 >= 1 && num4 <= num && num4 < strikeTimer.LastBeepSecond)
					{
						PlayClip(_countdownBeep);
					}
					strikeTimer.LastBeepSecond = num4;
				}
			}
		}

		private void PlayClip(AudioClip? clip)
		{
			if (!((Object)(object)_audioSource == (Object)null) && !((Object)(object)clip == (Object)null))
			{
				_audioSource.PlayOneShot(clip, Mathf.Clamp01(_beepVolume.Value));
			}
		}

		private void OnGUI()
		{
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			if (!_enabled.Value || !_showCountdown.Value || _activeStrikes.Count == 0)
			{
				return;
			}
			_remainingTimes.Clear();
			float num = Mathf.Max(0f, _warningStartsAtSeconds.Value);
			foreach (StrikeTimer activeStrike in _activeStrikes)
			{
				float num2 = activeStrike.EndTime - Time.time;
				if (!(num2 <= 0f) && (!_showOnlyDuringWarning.Value || !(num2 > num)))
				{
					_remainingTimes.Add(num2);
				}
			}
			if (_remainingTimes.Count != 0)
			{
				_remainingTimes.Sort();
				EnsureStyle();
				int num3 = Mathf.Min(_remainingTimes.Count, Mathf.Clamp(_maxVisibleTimers.Value, 1, 10));
				float num4 = Mathf.Max(34f, (float)_fontSize.Value + 10f);
				float num5 = (float)num3 * num4;
				float num6 = Mathf.Clamp01(_verticalPosition.Value) * (float)Screen.height - num5 * 0.5f;
				Rect rect = default(Rect);
				for (int i = 0; i < num3; i++)
				{
					float num7 = _remainingTimes[i];
					string arg = ((_remainingTimes.Count > 1) ? $" {i + 1}" : string.Empty);
					string text = $"{_labelText.Value}{arg}  —  {num7:0.0}s";
					((Rect)(ref rect))..ctor(0f, num6 + (float)i * num4, (float)Screen.width, num4);
					bool num8 = num7 <= num;
					float num9 = (num8 ? (0.82f + Mathf.Sin(Time.time * 10f) * 0.18f) : 1f);
					Color foreground = (Color)(num8 ? new Color(1f, 0.23f * num9, 0.12f * num9, 1f) : Color.white);
					DrawOutlinedLabel(rect, text, foreground);
				}
			}
		}

		private void EnsureStyle()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			if (_timerStyle == null)
			{
				_timerStyle = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4,
					fontStyle = (FontStyle)1,
					richText = false
				};
			}
			_timerStyle.fontSize = Mathf.Clamp(_fontSize.Value, 12, 96);
		}

		private void DrawOutlinedLabel(Rect rect, string text, Color foreground)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			if (_timerStyle != null)
			{
				Color textColor = _timerStyle.normal.textColor;
				_timerStyle.normal.textColor = new Color(0f, 0f, 0f, 0.85f);
				GUI.Label(new Rect(((Rect)(ref rect)).x - 2f, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), text, _timerStyle);
				GUI.Label(new Rect(((Rect)(ref rect)).x + 2f, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), text, _timerStyle);
				GUI.Label(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y - 2f, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), text, _timerStyle);
				GUI.Label(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 2f, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), text, _timerStyle);
				_timerStyle.normal.textColor = foreground;
				GUI.Label(rect, text, _timerStyle);
				_timerStyle.normal.textColor = textColor;
			}
		}
	}
}