Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of TouhouNuclearOverlay v1.6.2
plugins/TouhouNuclearOverlay.dll
Decompiled 2 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyVersion("0.0.0.0")] namespace TouhouNuclearOverlay; [BepInPlugin("com.cutyimodo.touhounuclearoverlay", "Touhou Nuclear Overlay", "1.6.2")] public class Plugin : BaseUnityPlugin { public const string GUID = "com.cutyimodo.touhounuclearoverlay"; public const string NAME = "Touhou Nuclear Overlay"; public const string VERSION = "1.6.2"; private static Plugin Instance; private static bool overlayActive = false; private static GameObject overlayRoot; private static float scrollOffset = 0f; private static Texture2D cautionTex; private static Texture2D radTex; private static Texture2D radTiledTex; private static object dockedApparatus = null; private static bool hasCheckedApparatus = false; private static Type lungPropType; private static Type hudManagerType; private static bool vanillaWarningDisabled = false; private static float suppressTimer = 0f; private static Type startOfRoundType; private static int overlayPhase = 0; private static float phaseTimer = 0f; private const float BG_OPACITY = 0f; private const float CAUTION_HEIGHT = 0.15f; private const float CAUTION_TOP_OFFSET = 0.05f; private const float CAUTION_BOT_OFFSET = 0.05f; private const float CAUTION_UV_X = 2f; private const float CAUTION_BREATHE = 1f; private const float CAUTION_BREATHE_SPEED = 1.5f; private const float CAUTION_SCROLL = 0.15f; private const float RAD_SIZE_RATIO = 5f / 18f; private const float RAD_GAP_RATIO = 1f / 3f; private const float RAD_Y_CENTER = 0.5f; private const float RAD_OPACITY = 0.5f; private const float RAD_SCROLL = 0.2f; private const float FADE_IN = 1f; private const float HOLD = 8f; private const float FADE_OUT = 1f; private static AudioClip alertClip; private static AudioSource alertSource; private static bool audioLoaded = false; private static CanvasGroup canvasGroupRef; private static RawImage topImg; private static RawImage bottomImg; private static List<RawImage> radImages = new List<RawImage>(); private void Awake() { Instance = this; cautionTex = LoadEmbeddedTexture("TouhouNuclearOverlay.caution.png"); radTex = LoadEmbeddedTexture("TouhouNuclearOverlay.radiation.png"); alertClip = LoadEmbeddedWav("TouhouNuclearOverlay.alert.wav"); if ((Object)(object)alertClip != (Object)null) { audioLoaded = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Alert sound loaded ({alertClip.length}s)"); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Alert sound not found in embedded resources"); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Touhou Nuclear Overlay v1.6.2 loaded!"); } private static Texture2D LoadEmbeddedTexture(string resourceName) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown Assembly executingAssembly = Assembly.GetExecutingAssembly(); using Stream stream = executingAssembly.GetManifestResourceStream(resourceName); if (stream == null) { Debug.LogWarning((object)("[TouhouNuclearOverlay] Resource not found: " + resourceName)); return Texture2D.whiteTexture; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); Type type = typeof(Texture2D).Assembly.GetType("UnityEngine.ImageConversion"); if (type == null) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { type = assembly.GetType("UnityEngine.ImageConversion"); if (type != null) { break; } } } if (type != null) { MethodInfo method = type.GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }); if (method != null) { method.Invoke(null, new object[2] { val, array }); } } ((Texture)val).wrapMode = (TextureWrapMode)0; return val; } private static object GetSOR() { if (startOfRoundType == null) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { startOfRoundType = assembly.GetType("StartOfRound"); if (startOfRoundType != null) { break; } } } if (startOfRoundType == null) { return null; } PropertyInfo property = startOfRoundType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public); if (property != null) { return property.GetValue(null); } FieldInfo field = startOfRoundType.GetField("Instance", BindingFlags.Static | BindingFlags.Public); if (field != null) { return field.GetValue(null); } return null; } private static bool GetBool(object obj, string name) { if (obj == null) { return false; } Type type = obj.GetType(); PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public); if (property != null) { return (bool)property.GetValue(obj); } FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public); if (field != null) { return (bool)field.GetValue(obj); } return false; } private void Update() { //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: 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_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_0308: 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_03a5: Unknown result type (might be due to invalid IL or missing references) //IL_03aa: Unknown result type (might be due to invalid IL or missing references) //IL_03c9: Unknown result type (might be due to invalid IL or missing references) //IL_03f0: Unknown result type (might be due to invalid IL or missing references) try { object sOR = GetSOR(); if (sOR != null && GetBool(sOR, "shipHasLanded") && !hasCheckedApparatus) { FindDockedApparatus(); hasCheckedApparatus = true; } if (sOR != null && !GetBool(sOR, "shipHasLanded") && !GetBool(sOR, "shipIsLeaving") && hasCheckedApparatus) { hasCheckedApparatus = false; dockedApparatus = null; CleanupOverlay(); } if (sOR == null && hasCheckedApparatus) { hasCheckedApparatus = false; dockedApparatus = null; CleanupOverlay(); } if (dockedApparatus != null && !GetBool(dockedApparatus, "isLungDocked")) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Apparatus was taken! Triggering overlay."); dockedApparatus = null; TriggerOverlay(); } if (overlayPhase <= 0) { return; } phaseTimer += Time.deltaTime; scrollOffset += Time.deltaTime; suppressTimer += Time.deltaTime; if (suppressTimer >= 0.5f) { suppressTimer = 0f; SuppressVanillaRadiationWarning(); } float alpha = 0f; switch (overlayPhase) { case 1: alpha = Mathf.Clamp01(phaseTimer / 1f); if (phaseTimer >= 1f) { overlayPhase = 2; phaseTimer = 0f; } break; case 2: alpha = 1f; if (phaseTimer >= 8f) { overlayPhase = 3; phaseTimer = 0f; } break; case 3: alpha = 1f - Mathf.Clamp01(phaseTimer / 1f); if (phaseTimer >= 1f) { CleanupOverlay(); } break; } if ((Object)(object)canvasGroupRef != (Object)null) { canvasGroupRef.alpha = alpha; } float num = 0.5f + 0.5f * Mathf.Sin(Time.time * 1.5f * (float)Math.PI); float num2 = 0f + 1f * num; if ((Object)(object)topImg != (Object)null) { Rect uvRect = topImg.uvRect; ((Rect)(ref uvRect)).x = scrollOffset * 0.15f; topImg.uvRect = uvRect; ((Graphic)topImg).color = new Color(1f, 1f, 1f, num2); } if ((Object)(object)bottomImg != (Object)null) { Rect uvRect2 = bottomImg.uvRect; ((Rect)(ref uvRect2)).x = scrollOffset * 0.15f * 0.8f; bottomImg.uvRect = uvRect2; ((Graphic)bottomImg).color = new Color(1f, 1f, 1f, num2); } float num3 = radSizePx(); float num4 = num3 * (1f / 3f); float num5 = num3 + num4; int count = radImages.Count; float num6 = (float)count * num5; for (int i = 0; i < count; i++) { if (!((Object)(object)radImages[i] != (Object)null)) { continue; } RectTransform component = ((Component)radImages[i]).GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null) { Vector2 anchoredPosition = component.anchoredPosition; anchoredPosition.x += 0.2f * (float)Screen.width * Time.deltaTime; if (anchoredPosition.x > (float)Screen.width + num3) { anchoredPosition.x -= num6; } component.anchoredPosition = anchoredPosition; } } } catch (Exception) { } } private float radSizePx() { return (float)Screen.height * (5f / 18f); } private void CleanupOverlay() { if ((Object)(object)overlayRoot != (Object)null) { Object.Destroy((Object)(object)overlayRoot); overlayRoot = null; } overlayActive = false; overlayPhase = 0; canvasGroupRef = null; topImg = null; bottomImg = null; radImages.Clear(); } private void FindDockedApparatus() { if (lungPropType == null) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { lungPropType = assembly.GetType("LungProp"); if (lungPropType != null) { break; } } } if (lungPropType == null) { return; } Object[] array = Object.FindObjectsOfType(lungPropType); if (array == null) { return; } Object[] array2 = array; foreach (Object obj in array2) { if (GetBool(obj, "isLungDocked")) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Found docked Apparatus, watching for removal."); dockedApparatus = obj; break; } } } private static AudioClip LoadEmbeddedWav(string resourceName) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); using Stream stream = executingAssembly.GetManifestResourceStream(resourceName); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); if (array.Length < 44) { return null; } int num = array[22] | (array[23] << 8); int num2 = array[24] | (array[25] << 8) | (array[26] << 16) | (array[27] << 24); int num3 = array[34] | (array[35] << 8); int i = 12; int num4 = 0; int num5; for (; i < array.Length - 8; i += 8 + num5) { char c = (char)array[i]; string text = c.ToString(); c = (char)array[i + 1]; string text2 = c.ToString(); c = (char)array[i + 2]; string text3 = c.ToString(); c = (char)array[i + 3]; string text4 = text + text2 + text3 + c; num5 = array[i + 4] | (array[i + 5] << 8) | (array[i + 6] << 16) | (array[i + 7] << 24); if (text4 == "data") { i += 8; num4 = num5; break; } } if (num4 == 0) { return null; } int num6 = num4 / (num3 / 8) / num; float[] array2 = new float[num6 * num]; int num7 = i; for (int j = 0; j < array2.Length; j++) { if (num7 >= array.Length - 1) { break; } short num8 = (short)(array[num7] | (array[num7 + 1] << 8)); array2[j] = (float)num8 / 32768f; num7 += 2; } AudioClip val = AudioClip.Create("alert", num6, num, num2, false); val.SetData(array2, 0); return val; } private void SuppressVanillaRadiationWarning() { try { if (hudManagerType == null) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { hudManagerType = assembly.GetType("HUDManager"); if (hudManagerType != null) { break; } } } if (hudManagerType == null) { return; } PropertyInfo property = hudManagerType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public); object obj = ((property != null) ? property.GetValue(null) : null); if (obj == null) { FieldInfo field = hudManagerType.GetField("Instance", BindingFlags.Static | BindingFlags.Public); obj = ((field != null) ? field.GetValue(null) : null); } if (obj == null) { return; } FieldInfo field2 = hudManagerType.GetField("RadiationWarningHUD", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field2 != null) { object value = field2.GetValue(obj); GameObject val = (GameObject)((value is GameObject) ? value : null); if (val != null && val.activeSelf) { val.SetActive(false); } else { Behaviour val2 = (Behaviour)((value is Behaviour) ? value : null); if (val2 != null && val2.enabled) { val2.enabled = false; } } } FieldInfo field3 = hudManagerType.GetField("radiationWarningAudio", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field3 != null) { object value2 = field3.GetValue(obj); if (value2 != null) { PropertyInfo property2 = value2.GetType().GetProperty("mute", BindingFlags.Instance | BindingFlags.Public); if (property2 != null) { property2.SetValue(value2, true); } MethodInfo method = value2.GetType().GetMethod("Stop", Type.EmptyTypes); if (method != null) { method.Invoke(value2, null); } } } FieldInfo field4 = hudManagerType.GetField("radiationGraphicAnimator", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field4 != null) { object value3 = field4.GetValue(obj); Behaviour val3 = (Behaviour)((value3 is Behaviour) ? value3 : null); if (val3 != null && val3.enabled) { val3.enabled = false; } } } catch (Exception) { } } private void PlayAlertSound() { if (audioLoaded && !((Object)(object)alertClip == (Object)null)) { if ((Object)(object)alertSource == (Object)null) { alertSource = ((Component)this).gameObject.AddComponent<AudioSource>(); alertSource.spatialBlend = 0f; alertSource.loop = false; alertSource.playOnAwake = false; alertSource.priority = 0; } alertSource.clip = alertClip; alertSource.volume = 1f; alertSource.Play(); } } private void TriggerOverlay() { if (overlayActive) { return; } overlayActive = true; overlayPhase = 1; phaseTimer = 0f; scrollOffset = 0f; try { CreateOverlay(); PlayAlertSound(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Overlay created successfully!"); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to create overlay: {arg}"); CleanupOverlay(); } } private void CreateOverlay() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Expected O, but got Unknown //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_034f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)overlayRoot != (Object)null) { Object.Destroy((Object)(object)overlayRoot); } overlayRoot = new GameObject("TouhouNuclearOverlay"); Object.DontDestroyOnLoad((Object)(object)overlayRoot); Canvas val = overlayRoot.AddComponent<Canvas>(); val.renderMode = (RenderMode)0; val.sortingOrder = 10000; canvasGroupRef = overlayRoot.AddComponent<CanvasGroup>(); canvasGroupRef.alpha = 0f; canvasGroupRef.blocksRaycasts = false; canvasGroupRef.interactable = false; float num = Screen.width; float num2 = Screen.height; GameObject val2 = CreateChild(overlayRoot, "Bg"); RawImage val3 = val2.AddComponent<RawImage>(); ((Graphic)val3).color = new Color(0f, 0f, 0f, 0f); StretchFill(val2); float minY = 0.79999995f; float maxY = 0.95f; GameObject val4 = CreateChild(overlayRoot, "TopBar"); SetAnchors(val4, 0f, minY, 1f, maxY); GameObject val5 = CreateChild(val4, "Img"); topImg = val5.AddComponent<RawImage>(); topImg.texture = (Texture)(object)cautionTex; topImg.uvRect = new Rect(0f, 0f, 2f, 1f); SetAnchors(val5, -0.5f, 0f, 1.5f, 1f); float minY2 = 0.05f; float maxY2 = 0.2f; GameObject val6 = CreateChild(overlayRoot, "BotBar"); SetAnchors(val6, 0f, minY2, 1f, maxY2); GameObject val7 = CreateChild(val6, "Img"); bottomImg = val7.AddComponent<RawImage>(); bottomImg.texture = (Texture)(object)cautionTex; bottomImg.uvRect = new Rect(0f, 0f, 2f, 1f); SetAnchors(val7, -0.5f, 0f, 1.5f, 1f); float num3 = radSizePx(); float num4 = num3 * (1f / 3f); float num5 = num3 + num4; int num6 = Mathf.CeilToInt(num / num5) + 3; float num7 = num2 * 0.5f; GameObject val8 = CreateChild(overlayRoot, "RadContainer"); StretchFill(val8); radImages.Clear(); for (int i = 0; i < num6; i++) { GameObject val9 = new GameObject("Rad" + i); val9.transform.SetParent(val8.transform, false); RectTransform val10 = val9.AddComponent<RectTransform>(); val10.sizeDelta = new Vector2(num3, num3); float num8 = 0f - num3 + (float)i * num5; val10.anchorMin = new Vector2(0f, 0.5f); val10.anchorMax = new Vector2(0f, 0.5f); val10.pivot = new Vector2(0f, 0.5f); val10.anchoredPosition = new Vector2(num8, 0f * num2); RawImage val11 = val9.AddComponent<RawImage>(); val11.texture = (Texture)(object)radTex; ((Graphic)val11).color = new Color(1f, 1f, 1f, 0.5f); radImages.Add(val11); } } private static GameObject CreateChild(GameObject parent, string name) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown GameObject val = new GameObject(name); val.transform.SetParent(parent.transform, false); val.AddComponent<RectTransform>(); return val; } private static void SetAnchors(GameObject go, float minX, float minY, float maxX, float maxY) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) RectTransform component = go.GetComponent<RectTransform>(); if (!((Object)(object)component == (Object)null)) { component.anchorMin = new Vector2(minX, minY); component.anchorMax = new Vector2(maxX, maxY); component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; } } private static void StretchFill(GameObject go) { SetAnchors(go, 0f, 0f, 1f, 1f); } }