Decompiled source of Ultrakill Timer v0.1.11

UltrakillTimer.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using On.RoR2;
using On.RoR2.UI;
using R2API.Utils;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using RoR2.UI;
using TMPro;
using UltrakillTimer.Utils;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("UltrakillTimer")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("UltrakillTimer")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("422fa411-163a-41e9-a5c6-f06c0d813884")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace UltrakillTimer
{
	public class AlwaysFollowCamera : MonoBehaviour
	{
		public bool keepFollowing = true;

		public void Awake()
		{
			StartFollowingCamera();
		}

		private IEnumerator FollowCamera()
		{
			if ((Object)(object)Camera.main != (Object)null)
			{
				((Component)this).transform.SetParent(((Component)Camera.main).transform, false);
			}
			yield return (object)new WaitForSeconds(3f);
			if (keepFollowing)
			{
				((MonoBehaviour)this).StartCoroutine("FollowCamera");
			}
		}

		private void StartFollowingCamera()
		{
			((MonoBehaviour)this).StartCoroutine("FollowCamera");
		}
	}
	public class AutoVolumeControl : MonoBehaviour
	{
		private AudioSource _audiosrc;

		private FieldInfo _volmaster;

		private FieldInfo _volmusic;

		private float _volume;

		private float _volumemod;

		private void Awake()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			_volumemod = 1f;
			_audiosrc = ((Component)this).GetComponent<AudioSource>();
			_volmaster = typeof(AudioManager).GetField("cvVolumeMaster", BindingFlags.Static | BindingFlags.NonPublic);
			_volmusic = typeof(AudioManager).GetField("cvVolumeMsx", BindingFlags.Static | BindingFlags.NonPublic);
			PauseScreenController.OnDisable += new hook_OnDisable(OnUnpause);
			PauseScreenController.OnEnable += new hook_OnEnable(OnPause);
		}

		public static float GetVolume()
		{
			FieldInfo? field = typeof(AudioManager).GetField("cvVolumeMaster", BindingFlags.Static | BindingFlags.NonPublic);
			FieldInfo field2 = typeof(AudioManager).GetField("cvVolumeMsx", BindingFlags.Static | BindingFlags.NonPublic);
			float num = float.Parse(Reflection.InvokeMethod<string>(field.GetValue(null), "GetString"), CultureInfo.InvariantCulture) / 100f;
			float num2 = float.Parse(Reflection.InvokeMethod<string>(field2.GetValue(null), "GetString"), CultureInfo.InvariantCulture) / 100f;
			return (UltrakillTimerPlugin.IgnoreIGVolume ? 1f : num2) * num;
		}

		private void Update()
		{
			float num = float.Parse(Reflection.InvokeMethod<string>(_volmaster.GetValue(null), "GetString"), CultureInfo.InvariantCulture) / 100f;
			float num2 = float.Parse(Reflection.InvokeMethod<string>(_volmusic.GetValue(null), "GetString"), CultureInfo.InvariantCulture) / 100f;
			_volume = num * (UltrakillTimerPlugin.IgnoreIGVolume ? 1f : num2);
			_audiosrc.volume = num * (UltrakillTimerPlugin.IgnoreIGVolume ? 1f : num2) * _volumemod * UltrakillTimerPlugin.MusicVolumeConfig;
		}

		private void OnDestroy()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			PauseScreenController.OnDisable -= new hook_OnDisable(OnUnpause);
			PauseScreenController.OnEnable -= new hook_OnEnable(OnPause);
		}

		private void OnUnpause(orig_OnDisable orig, PauseScreenController self)
		{
			UltrakillTimerPlugin.LogDebug("Unpaused! Adjusting volume mod to 1f");
			orig.Invoke(self);
			((MonoBehaviour)this).StartCoroutine(ChangeVolumeGradually(1f, 0.5f));
		}

		private void OnPause(orig_OnEnable orig, PauseScreenController self)
		{
			UltrakillTimerPlugin.LogDebug("Paused! Adjusting volume mod to 0.25f");
			orig.Invoke(self);
			((MonoBehaviour)this).StartCoroutine(ChangeVolumeGradually(0.25f, 0.5f));
		}

		private IEnumerator ChangeVolumeGradually(float volume, float t)
		{
			float ct = 0f;
			float oldvolumemod = _volumemod;
			while (ct < t)
			{
				UltrakillTimerPlugin.LogDebug($"{Time.unscaledDeltaTime} : {ct} / {t} .. {_volumemod} to {volume}");
				ct += Time.unscaledDeltaTime;
				_volumemod = Mathf.Lerp(oldvolumemod, volume, ct / t);
				_audiosrc.volume = _volume * _volumemod * UltrakillTimerPlugin.MusicVolumeConfig;
				yield return (object)new WaitForEndOfFrame();
			}
		}
	}
	public static class MusicController
	{
		private static GameObject _gomc;

		private static AudioSource _audiosrc;

		private static AlwaysFollowCamera _camfollower;

		public static AudioClip phase1;

		public static AudioClip phase2;

		public static bool stopMusicOnSceneChange;

		public static byte currentPhase { get; private set; }

		public static float Time
		{
			get
			{
				if ((Object)(object)_audiosrc == (Object)null)
				{
					return 0f;
				}
				return _audiosrc.time;
			}
		}

		static MusicController()
		{
			stopMusicOnSceneChange = true;
			currentPhase = 0;
			SceneManager.activeSceneChanged += OnSceneChange;
		}

		public static void CreateMusicController()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (!((Object)(object)_gomc != (Object)null))
			{
				_gomc = new GameObject("UltrakillTimer MusicController");
				_audiosrc = _gomc.AddComponent<AudioSource>();
				_audiosrc.minDistance = 1000f;
				_audiosrc.maxDistance = 10000f;
				_audiosrc.loop = true;
				_gomc.AddComponent<AutoVolumeControl>();
				_camfollower = _gomc.AddComponent<AlwaysFollowCamera>();
			}
		}

		public static void DestroyMusicController()
		{
			Object.Destroy((Object)(object)_gomc);
		}

		public static void AttemptLoadMusic()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			log("Attempting to load audio data...");
			if ((Object)(object)phase1 != (Object)null)
			{
				log("Loading phase 1 audio data");
				if (!phase1.LoadAudioData())
				{
					logerr($"FAILURE!!!!!!!!! load state ended up to be {phase1.loadState}");
				}
				else
				{
					log("Loaded phase 1 audio data successfully");
				}
			}
			if ((Object)(object)phase2 != (Object)null)
			{
				log("Loading phase 2 audio data");
				if (!phase2.LoadAudioData())
				{
					logerr($"FAILURE!!!!!!!!! load state ended up to be {phase1.loadState}");
				}
				else
				{
					log("Loaded phase 2 audio data successfully");
				}
			}
			static void log(string msg)
			{
				UltrakillTimerPlugin.LogInfo(msg);
			}
			static void logerr(string msg)
			{
				UltrakillTimerPlugin.LogError(msg);
			}
		}

		private static void OnSceneChange(Scene from, Scene to)
		{
			if (((Scene)(ref to)).name == "moon2")
			{
				AttemptLoadMusic();
			}
			if (!((Object)(object)_gomc == (Object)null) && stopMusicOnSceneChange)
			{
				Stop();
			}
		}

		public static void Play(AudioClip clip)
		{
			if ((Object)(object)_gomc == (Object)null || InstanceExists())
			{
				CreateMusicController();
			}
			_audiosrc.clip = clip;
			_audiosrc.volume = AutoVolumeControl.GetVolume();
			_audiosrc.Play();
		}

		public static void Stop()
		{
			if (!((Object)(object)_gomc == (Object)null) && !((Object)(object)_audiosrc == (Object)null))
			{
				_audiosrc.Stop();
				currentPhase = 0;
			}
		}

		public static bool InstanceExists()
		{
			return (Object)(object)_audiosrc != (Object)null;
		}

		public static void LoadPhase(byte phase, AudioClip clip)
		{
			if (phase == 1)
			{
				phase1 = clip;
			}
			if (phase == 2)
			{
				phase2 = clip;
			}
		}

		public static void PlayPhase(byte phase)
		{
			currentPhase = phase;
			if (phase == 1)
			{
				Play(phase1);
			}
			if (phase == 2)
			{
				Play(phase2);
			}
		}
	}
	public class PhaseChangeCollisionCheck : MonoBehaviour
	{
		public static event Action<GameObject> OnCollisionEnterEvent;

		public static void AddComponentToPortals()
		{
			foreach (GameObject item in from x in Object.FindObjectsOfType<GameObject>()
				where ((Object)x).name.Contains("MoonExitArenaOrb")
				select x)
			{
				item.AddComponent<PhaseChangeCollisionCheck>();
			}
		}

		public void OnTriggerEnter(Collider c)
		{
			UltrakillTimerPlugin.LogDebug("Collision detected from " + ((Object)((Component)c).gameObject).name);
			if ((Object)(object)((Component)c).gameObject.GetComponent<CharacterBody>() != (Object)null)
			{
				PhaseChangeCollisionCheck.OnCollisionEnterEvent(((Component)c).gameObject);
			}
		}
	}
	public class TimerController : MonoBehaviour
	{
		private float _timer;

		public FixedTimeStamp timerEnd;

		public Color originalColor;

		public Color flashColor;

		public float fadeTime;

		public float delay;

		public bool useCustomTimerEnd;

		public float customTimerEnd;

		private TextMeshProUGUI timerText;

		private TextMeshProUGUI headerText;

		public void Awake()
		{
			timerText = ((Component)((Component)this).transform.GetChild(2)).gameObject.GetComponent<TextMeshProUGUI>();
			headerText = ((Component)((Component)this).transform.GetChild(1)).gameObject.GetComponent<TextMeshProUGUI>();
		}

		public void Update()
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			_timer += Time.deltaTime;
			float num = _timer;
			if (MusicController.InstanceExists())
			{
				num = MusicController.Time;
			}
			string[] array = (useCustomTimerEnd ? (customTimerEnd - _timer) : ((FixedTimeStamp)(ref timerEnd)).timeUntilClamped).ToString(CultureInfo.InvariantCulture).Split(new char[1] { '.' });
			((TMP_Text)timerText).text = array[0] + "<size=40%>." + array[1].Substring(0, (array[1].Length > 2) ? 2 : array[1].Length);
			((Graphic)timerText).color = Color.Lerp(flashColor, originalColor, num % fadeTime + delay);
			((Graphic)headerText).color = Color.Lerp(flashColor, originalColor, num % fadeTime + delay);
		}

		public void ResetTimer()
		{
			_timer = 0f;
		}
	}
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.kanggamming.ultrakilltimer", "ULTRAKILL Timer", "0.1.0")]
	public class UltrakillTimerPlugin : BaseUnityPlugin
	{
		private AssetBundle _ab;

		private AssetBundle _abm;

		private GameObject _timer;

		private GameObject _currenttimer;

		private FixedTimeStamp _endtime;

		internal static ManualLogSource _log;

		private float _previewTime;

		private GameObject _previewTimer;

		private bool _preview;

		private static ConfigEntry<bool> LoadMusicBundle { get; set; }

		private static ConfigEntry<bool> OverridePulseBPM { get; set; }

		private static ConfigEntry<int> CustomPulseBPM { get; set; }

		private static ConfigEntry<float> BackgroundAlpha { get; set; }

		private static ConfigEntry<Color> NormalColor { get; set; }

		private static ConfigEntry<Color> FlashColor { get; set; }

		private static ConfigEntry<float> MusicVolume { get; set; }

		private static ConfigEntry<bool> IgnoreInGameMusicVolume { get; set; }

		private static ConfigEntry<float> TimerTimePreview { get; set; }

		internal static float MusicVolumeConfig => MusicVolume.Value;

		internal static bool IgnoreIGVolume => IgnoreInGameMusicVolume.Value;

		public void Awake()
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Expected O, but got Unknown
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Expected O, but got Unknown
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Expected O, but got Unknown
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Expected O, but got Unknown
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: 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_0211: 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_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Expected O, but got Unknown
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Expected O, but got Unknown
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Expected O, but got Unknown
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Expected O, but got Unknown
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Expected O, but got Unknown
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Expected O, but got Unknown
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Expected O, but got Unknown
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Expected O, but got Unknown
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Expected O, but got Unknown
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: Expected O, but got Unknown
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_0378: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Expected O, but got Unknown
			//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03aa: Expected O, but got Unknown
			//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cf: Expected O, but got Unknown
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d4: Expected O, but got Unknown
			//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f9: Expected O, but got Unknown
			//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fe: Expected O, but got Unknown
			//IL_0419: Unknown result type (might be due to invalid IL or missing references)
			//IL_0423: Expected O, but got Unknown
			//IL_041e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0428: Expected O, but got Unknown
			//IL_042d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			//IL_043d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			//IL_0453: Unknown result type (might be due to invalid IL or missing references)
			//IL_045e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0469: Unknown result type (might be due to invalid IL or missing references)
			//IL_0479: Expected O, but got Unknown
			//IL_0474: Unknown result type (might be due to invalid IL or missing references)
			//IL_047e: Expected O, but got Unknown
			//IL_0499: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a3: Expected O, but got Unknown
			//IL_049e: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a8: Expected O, but got Unknown
			//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cd: Expected O, but got Unknown
			//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d2: Expected O, but got Unknown
			//IL_04ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f7: Expected O, but got Unknown
			//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fc: Expected O, but got Unknown
			//IL_0626: Unknown result type (might be due to invalid IL or missing references)
			//IL_0630: Expected O, but got Unknown
			//IL_0637: Unknown result type (might be due to invalid IL or missing references)
			//IL_0641: Expected O, but got Unknown
			_log = ((BaseUnityPlugin)this).Logger;
			LoadMusicBundle = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "LoadMusicBundle", true, "Whether to load the music bundle. This is required to play the music from 7-4 in ULTRAKILL while escaping the moon.");
			OverridePulseBPM = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "OverridePulseBPM", false, "Whether to override the BPM of the pulsing animation for the timer. The timer pulses every 1/2 beat, and the default BPM is 120 BPM, so 120 BPM = Pulse every 1 second");
			CustomPulseBPM = ((BaseUnityPlugin)this).Config.Bind<int>("Visual", "CustomPulseBPM", 120, "Refer to the description of Override Pulse BPM");
			BackgroundAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "BackgroundAlpha", 170f, "The alpha value/opacity of the background panel of the timer. Default is 220, min is 0, max is 255");
			NormalColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Visual", "NormalColor", new Color(1f, 0f, 0f, 1f), "The normal color the timer uses.");
			FlashColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Visual", "FlashColor", new Color(1f, 1f, 0f, 1f), "The color the timer pulses.");
			MusicVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Music", "MusicVolume", 1f, "The volume of the music. The music is already affected by the in-game volume sliders, but feel free to adjust the volume of the escape music with this as well!");
			IgnoreInGameMusicVolume = ((BaseUnityPlugin)this).Config.Bind<bool>("Music", "IgnoreInGameMusicVolume", false, "If true, ignores the in-game volume.");
			TimerTimePreview = ((BaseUnityPlugin)this).Config.Bind<float>("Misc", "TimerTimePreview", 80f, "Used for in-game settings menu made with Risk of Options, please ignore");
			ModSettingsManager.SetModDescription("A plugin that replaces the in-game timer for the moon escape sequence with the timer from 7-4 in ULTRAKILL");
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(LoadMusicBundle, new CheckBoxConfig
			{
				category = "General",
				description = "Whether to load the music bundle. This is required to play the music from 7-4 in ULTRAKILL while escaping the moon. Only affects startup, so restarting the game is required to toggle this option.\n\n(This option is really pointless as of now, but maybe it'll have a use in a future update.)",
				restartRequired = true,
				name = "Load music bundle on start"
			}));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(OverridePulseBPM, new CheckBoxConfig
			{
				category = "Visual",
				description = "Overrides the default BPM of the pulse animation for the timer.",
				restartRequired = false,
				name = "Override pulse BPM"
			}));
			ModSettingsManager.AddOption((BaseOption)new IntSliderOption(CustomPulseBPM, new IntSliderConfig
			{
				category = "Visual",
				description = "Changes the BPM of the pulse animation if \"Override pulse BPM\" is enabled. The timer pulses every 1/2 beat, and the default BPM is 120 BPM, so with 120 BPM the timer would pulse every second.",
				restartRequired = false,
				min = 1,
				max = 1000,
				name = "Custom BPM"
			}));
			ModSettingsManager.AddOption((BaseOption)new StepSliderOption(BackgroundAlpha, new StepSliderConfig
			{
				category = "Visual",
				description = "The alpha value/opacity of the background color on the timer. Default is 220, min is 0 and max is 255.",
				min = 0f,
				max = 255f,
				increment = 1f,
				formatString = "{0:G}",
				name = "Background opacity"
			}));
			ModSettingsManager.AddOption((BaseOption)new ColorOption(NormalColor, new ColorOptionConfig
			{
				category = "Visual",
				description = "The color of the timer. The default value is purely red.",
				restartRequired = false,
				name = "Timer color"
			}));
			ModSettingsManager.AddOption((BaseOption)new ColorOption(FlashColor, new ColorOptionConfig
			{
				category = "Visual",
				description = "The color the timer pulses. The default value is purely yellow.",
				restartRequired = false,
				name = "Timer flash color"
			}));
			ModSettingsManager.AddOption((BaseOption)new SliderOption(MusicVolume, new SliderConfig
			{
				category = "Music",
				description = "The volume of the music. The music is already affected by the in-game volume sliders, but feel free to adjust the volume of the escape music with this as well! (1.00 is 100%, default is 1.00)",
				restartRequired = false,
				min = 0f,
				formatString = "{0:G}",
				max = 3f,
				name = "Escape music volume"
			}));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(IgnoreInGameMusicVolume, new CheckBoxConfig
			{
				category = "Music",
				description = "Ignore the value of the music volume found in the Audio page in the actual Risk of Rain 2 settings page.",
				restartRequired = false,
				name = "Ignore in-game music volume"
			}));
			ModSettingsManager.AddOption((BaseOption)new GenericButtonOption("Preview Music 1", "Preview", "Listen to the first phase of the escape music, played right after the moon detonation becomes imminent and before you enter one of the portals to escape the arena.", "Play", new UnityAction(TestMusic1)));
			ModSettingsManager.AddOption((BaseOption)new GenericButtonOption("Preview Music 2", "Preview", "Listen to the second phase of the escape music, played right after you touch one of the portals that lead you out of the arena.", "Play", new UnityAction(TestMusic2)));
			ModSettingsManager.AddOption((BaseOption)new GenericButtonOption("Stop Music Preview", "Preview", "Stop previewing the custom escape music.", "Stop", new UnityAction(StopAllMusic)));
			ModSettingsManager.AddOption((BaseOption)new StepSliderOption(TimerTimePreview, new StepSliderConfig
			{
				category = "Preview",
				description = "Amount of seconds that the timer will start ticking down from. Used only in the preview of the timer.",
				name = "Timer Preview's Time",
				min = 0f,
				max = 600f,
				increment = 1f
			}));
			ModSettingsManager.AddOption((BaseOption)new GenericButtonOption("Preview Timer", "Preview", "Spawn the timer at the top and play the music as well.\n\n(NOTE: If you want to edit visual settings while previewing, you need to click on this button again to see changes)", "Preview", new UnityAction(PreviewTimerWithMusic)));
			ModSettingsManager.AddOption((BaseOption)new GenericButtonOption("Preview Timer w/o Music", "Preview", "Spawn the timer at the top but don't play the music.\n\n(NOTE: If you want to edit visual settings while previewing, you need to click on this button again to see changes)", "Preview", new UnityAction(PreviewTimer)));
			ModSettingsManager.AddOption((BaseOption)new GenericButtonOption("Destroy Timer Preview", "Preview", "Stops displaying the timer and playing the music.", "Destroy", new UnityAction(KillTimer)));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loading timer asset bundle");
			_ab = AssetBundle.LoadFromMemory(GetEmbeddedResource("ultrakilltimerbundle"));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loading timer prefab...");
			_timer = _ab.LoadAsset<GameObject>("assets/critical failure timer.prefab");
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Loaded prefab " + ((Object)_timer).name + " successfully."));
			((BaseUnityPlugin)this).Logger.LogInfo((object)(LoadMusicBundle.Value ? "Loading escape music asset bundle" : "Skipping loading escape music asset bundle"));
			if (LoadMusicBundle.Value)
			{
				_abm = AssetBundle.LoadFromMemory(GetEmbeddedResource("ultrakilltimersoundbundle"));
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Loading music...");
				MusicController.phase1 = _abm.LoadAsset<AudioClip>("assets/centaur b-4.ogg");
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Phase 1 music loaded");
				MusicController.phase2 = _abm.LoadAsset<AudioClip>("assets/centaur b-5.ogg");
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Phase 2 music loaded");
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded escape music successfully.");
			}
			EscapeSequenceController.SetHudCountdownEnabled += new hook_SetHudCountdownEnabled(SetHUDCountdownEnabled);
			EscapeSequenceMainState.OnEnter += new hook_OnEnter(EscapeSeqMainStateOnEnter);
			PhaseChangeCollisionCheck.OnCollisionEnterEvent += OnEnterArenaPortal;
		}

		internal static void LogInfo(string msg)
		{
			_log.LogInfo((object)msg);
		}

		internal static void LogError(string msg)
		{
			_log.LogError((object)msg);
		}

		internal static void LogWarning(string msg)
		{
			_log.LogWarning((object)msg);
		}

		internal static void LogDebug(string msg)
		{
			_log.LogDebug((object)msg);
		}

		private void TestMusic1()
		{
			MusicController.PlayPhase(1);
		}

		private void TestMusic2()
		{
			MusicController.PlayPhase(2);
		}

		private void TestMusic2IfStillPlaying()
		{
			if (_preview)
			{
				MusicController.PlayPhase(2);
			}
		}

		private void StopAllMusic()
		{
			MusicController.Stop();
			MusicController.DestroyMusicController();
		}

		private void PreviewTimerWithMusic()
		{
			_preview = true;
			if ((Object)(object)_previewTimer != (Object)null)
			{
				DestroyTimer(_previewTimer);
			}
			TestMusic1();
			CoroutineRunner.RunCoroutine(delaySwitch(), 18f);
			_previewTime = TimerTimePreview.Value;
			_previewTimer = CreateTimer(_previewTime);
			IEnumerator delaySwitch()
			{
				yield return (object)new WaitForSeconds(16f);
				TestMusic2IfStillPlaying();
			}
		}

		private void PreviewTimer()
		{
			if ((Object)(object)_previewTimer != (Object)null)
			{
				DestroyTimer(_previewTimer);
			}
			_previewTime = TimerTimePreview.Value;
			_previewTimer = CreateTimer(_previewTime);
		}

		private void KillTimer()
		{
			DestroyTimer(_previewTimer);
			StopAllMusic();
			_preview = false;
		}

		public void Update()
		{
		}

		private void OnEnterArenaPortal(GameObject obj)
		{
			if (MusicController.InstanceExists() && MusicController.currentPhase != 2)
			{
				MusicController.PlayPhase(2);
			}
		}

		private void EscapeSeqMainStateOnEnter(orig_OnEnter orig, EscapeSequenceMainState self)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			orig.Invoke(self);
			_endtime = Reflection.GetFieldValue<FixedTimeStamp>((object)self, "endTime");
			MusicController.PlayPhase(1);
			CoroutineRunner.RunCoroutine(AttachPhaseChangeChecks(), 1f);
		}

		private IEnumerator AttachPhaseChangeChecks()
		{
			yield return (object)new WaitForSeconds(0.25f);
			PhaseChangeCollisionCheck.AddComponentToPortals();
		}

		private void SetHUDCountdownEnabled(orig_SetHudCountdownEnabled orig, EscapeSequenceController self, HUD hud, bool shouldEnableCountdownPanel)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)_currenttimer) != shouldEnableCountdownPanel)
			{
				if (shouldEnableCountdownPanel)
				{
					_currenttimer = CreateTimer(_endtime);
				}
				else
				{
					DestroyTimer(_currenttimer);
				}
			}
		}

		private void DestroyTimer(GameObject timer)
		{
			GameObject gameObject = ((Component)timer.transform.parent).gameObject;
			Object.Destroy((Object)(object)timer);
			Object.Destroy((Object)(object)gameObject);
		}

		private GameObject CreateTimer(FixedTimeStamp endTime)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.Find("Timer Canvas");
			Canvas val2;
			if ((Object)(object)val == (Object)null)
			{
				val = new GameObject("Timer Canvas");
				val2 = val.AddComponent<Canvas>();
				val2.renderMode = (RenderMode)0;
				val2.referencePixelsPerUnit = 100f;
				val2.scaleFactor = 1f;
			}
			else
			{
				val2 = val.GetComponent<Canvas>();
			}
			GameObject obj = Object.Instantiate<GameObject>(_timer, ((Component)val2).transform);
			Image component = ((Component)obj.transform.GetChild(0)).GetComponent<Image>();
			((Graphic)component).color = new Color(((Graphic)component).color.r, ((Graphic)component).color.g, ((Graphic)component).color.b, BackgroundAlpha.Value / 255f);
			TimerController timerController = obj.AddComponent<TimerController>();
			timerController.delay = 0f;
			timerController.fadeTime = ((!OverridePulseBPM.Value) ? 1 : (120 / CustomPulseBPM.Value));
			timerController.flashColor = FlashColor.Value;
			timerController.originalColor = NormalColor.Value;
			timerController.timerEnd = endTime;
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Timer created with {((FixedTimeStamp)(ref endTime)).timeUntilClamped}s, fadeTime = {timerController.fadeTime}");
			return obj;
		}

		private GameObject CreateTimer(float endTime)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.Find("Timer Canvas");
			Canvas val2;
			if ((Object)(object)val == (Object)null)
			{
				val = new GameObject("Timer Canvas");
				val2 = val.AddComponent<Canvas>();
				val2.renderMode = (RenderMode)0;
				val2.referencePixelsPerUnit = 100f;
				val2.scaleFactor = 1f;
			}
			else
			{
				val2 = val.GetComponent<Canvas>();
			}
			GameObject obj = Object.Instantiate<GameObject>(_timer, ((Component)val2).transform);
			Image component = ((Component)obj.transform.GetChild(0)).GetComponent<Image>();
			((Graphic)component).color = new Color(((Graphic)component).color.r, ((Graphic)component).color.g, ((Graphic)component).color.b, BackgroundAlpha.Value / 255f);
			TimerController timerController = obj.AddComponent<TimerController>();
			timerController.delay = 0f;
			timerController.fadeTime = (OverridePulseBPM.Value ? (120f / (float)CustomPulseBPM.Value) : 1f);
			timerController.flashColor = FlashColor.Value;
			timerController.originalColor = NormalColor.Value;
			timerController.useCustomTimerEnd = true;
			timerController.customTimerEnd = endTime;
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Timer created with {endTime}s, fadeTime = {timerController.fadeTime}");
			return obj;
		}

		private byte[] GetEmbeddedResource(string name)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Getting resource " + name));
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			byte[] array = null;
			string text = null;
			string[] manifestResourceNames = executingAssembly.GetManifestResourceNames();
			foreach (string text2 in manifestResourceNames)
			{
				if (text2.Contains(name))
				{
					text = text2;
				}
			}
			if (string.IsNullOrEmpty(text))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Resource " + text + " not found"));
				throw new ArgumentException("Embedded resource not found", "name");
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Found resource " + text));
			using Stream stream = executingAssembly.GetManifestResourceStream(text);
			array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			stream.Dispose();
			return array;
		}
	}
}
namespace UltrakillTimer.Utils
{
	public class CoroutineRunner : MonoBehaviour
	{
		public IEnumerator coroutine;

		public float timer;

		public static void RunCoroutine(IEnumerator coroutine, float destroytimer)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			CoroutineRunner coroutineRunner = new GameObject("Coroutine Runner").AddComponent<CoroutineRunner>();
			coroutineRunner.coroutine = coroutine;
			coroutineRunner.timer = destroytimer;
			coroutineRunner.StartCoroutineNow();
		}

		private void Awake()
		{
			((MonoBehaviour)this).StartCoroutine("DelayedDelayedDestroy");
		}

		private void StartCoroutineNow()
		{
			((MonoBehaviour)this).StartCoroutine(coroutine);
		}

		private IEnumerator DelayedDelayedDestroy()
		{
			yield return (object)new WaitForSeconds(0.25f);
			Object.Destroy((Object)(object)((Component)this).gameObject, timer - 0.25f);
		}
	}
}