Decompiled source of ComingInHotMod v1.0.0

MyRepoMod.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MyAudioMod;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MyRepoMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MyRepoMod")]
[assembly: AssemblyTitle("MyRepoMod")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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;
		}
	}
}
[HarmonyPatch(typeof(TumbleUI), "Update")]
public static class TumbleStartPatch
{
	private static bool wasActive;

	[HarmonyPostfix]
	public static void Postfix(TumbleUI __instance)
	{
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		if (!LevelGenerator.Instance.Generated)
		{
			return;
		}
		LoadingUI instance = LoadingUI.instance;
		if ((Object)(object)instance != (Object)null)
		{
			Type type = ((object)instance).GetType();
			FieldInfo fieldInfo = AccessTools.Field(type, "levelAnimationCompleted");
			if (fieldInfo != null && !(bool)(fieldInfo.GetValue(instance) ?? ((object)false)))
			{
				return;
			}
		}
		PlayerController instance2 = PlayerController.instance;
		if ((Object)(object)instance2 == (Object)null)
		{
			return;
		}
		Type type2 = ((object)instance2).GetType();
		FieldInfo fieldInfo2 = AccessTools.Field(type2, "InputDisableTimer");
		if (fieldInfo2 != null)
		{
			float num = (float)(fieldInfo2.GetValue(instance2) ?? ((object)0f));
			if (num > 0f)
			{
				return;
			}
		}
		PlayerAvatar playerAvatarScript = instance2.playerAvatarScript;
		if (!((Object)(object)playerAvatarScript == (Object)null))
		{
			Type type3 = ((object)playerAvatarScript).GetType();
			bool flag = (bool)(AccessTools.Field(type3, "isTumbling")?.GetValue(playerAvatarScript) ?? ((object)false));
			bool flag2 = (bool)(AccessTools.Field(type3, "isDisabled")?.GetValue(playerAvatarScript) ?? ((object)false));
			bool flag3 = flag && !flag2;
			if (flag3 && !wasActive && Time.timeSinceLevelLoad > 1f)
			{
				Plugin.Logger.LogInfo((object)"\ud83d\udd25 Tumble started — playing Hot.wav");
				Plugin.Instance?.PlayComingInHotAt(((Component)__instance).transform.position);
			}
			wasActive = flag3;
		}
	}
}
[HarmonyPatch(typeof(TumbleUI), "Update")]
public static class TumbleUI_Update_Patch
{
	private static bool previousCanExit;

	[HarmonyPostfix]
	public static void Postfix(TumbleUI __instance)
	{
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)__instance == (Object)null || (Object)(object)Plugin.Instance == (Object)null)
		{
			return;
		}
		FieldInfo fieldInfo = AccessTools.Field(typeof(TumbleUI), "canExit");
		FieldInfo fieldInfo2 = AccessTools.Field(typeof(TumbleUI), "canExitPrevious");
		if (fieldInfo == null || fieldInfo2 == null)
		{
			Plugin.Logger.LogError((object)"❌ Could not access canExit or canExitPrevious fields via reflection.");
			return;
		}
		bool flag = (bool)fieldInfo.GetValue(__instance);
		bool flag2 = (bool)fieldInfo2.GetValue(__instance);
		if (flag && !flag2)
		{
			Plugin.Logger.LogInfo((object)"\ud83d\udca5 Detected tumble exit transition — replacing sound with ComingInHot.wav");
			object? obj = AccessTools.Field(typeof(TumbleUI), "canExitSound")?.GetValue(__instance);
			Sound val = (Sound)((obj is Sound) ? obj : null);
			if ((Object)(object)val?.Source != (Object)null && val.Source.isPlaying)
			{
				val.Source.Stop();
				Plugin.Logger.LogInfo((object)"❌ Original tumble sound stopped.");
			}
			((MonoBehaviour)Plugin.Instance).StartCoroutine(PlaySoundDelayed(((Component)__instance).transform.position));
		}
	}

	private static IEnumerator PlaySoundDelayed(Vector3 position)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		yield return (object)new WaitForSeconds(0.1f);
		Plugin.Logger.LogInfo((object)$"\ud83d\udd0a Playing ComingInHot at {position}");
		Plugin.Instance.PlayComingInHotAt(position);
	}
}
namespace MyAudioMod
{
	[BepInPlugin("com.yourname.audioMod", "Audio Mod", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public class AutoDestroyAudio : MonoBehaviour
		{
			public float duration;

			private void Start()
			{
				Object.Destroy((Object)(object)((Component)this).gameObject, duration);
			}
		}

		private ManualLogSource _logger = null;

		private AudioClip? comingInHotClip;

		public static bool ReadyToPlayHot;

		public static ManualLogSource Logger => Instance._logger;

		public static Plugin Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			_logger = ((BaseUnityPlugin)this).Logger;
			Logger.LogInfo((object)"\ud83d\udd0a Audio Mod initializing...");
			Harmony.CreateAndPatchAll(typeof(Plugin), (string)null);
			Harmony.CreateAndPatchAll(typeof(TumbleStartPatch), (string)null);
			Harmony.CreateAndPatchAll(typeof(TumbleSoundReplacePatch), (string)null);
			((MonoBehaviour)this).StartCoroutine(MarkReadyToPlay());
			((MonoBehaviour)this).StartCoroutine(LoadEmbeddedClip("MyRepoMod.Hot.wav", delegate(AudioClip? clip)
			{
				comingInHotClip = clip;
			}));
		}

		private IEnumerator MarkReadyToPlay()
		{
			Logger.LogInfo((object)"\ud83d\udd53 Waiting 2 seconds before allowing Hot.wav playback...");
			yield return (object)new WaitForSeconds(2f);
			ReadyToPlayHot = true;
			Logger.LogInfo((object)"✅ ReadyToPlayHot is now TRUE");
		}

		private IEnumerator SetupInputHandler()
		{
			yield return (object)new WaitForSeconds(2f);
			GameObject go = new GameObject("AudioInputHandler");
			Object.DontDestroyOnLoad((Object)(object)go);
			go.AddComponent<AudioUpdate>().Plugin = this;
		}

		private IEnumerator LoadEmbeddedClip(string resourceName, Action<AudioClip?> callback)
		{
			Assembly assembly = Assembly.GetExecutingAssembly();
			using Stream stream = assembly.GetManifestResourceStream(resourceName);
			if (stream == null)
			{
				Logger.LogError((object)("❌ Embedded WAV not found: " + resourceName));
				yield break;
			}
			string tempPath = Path.Combine(Application.temporaryCachePath, Path.GetFileName(resourceName));
			using (FileStream file = File.Create(tempPath))
			{
				stream.CopyTo(file);
			}
			UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip("file://" + tempPath, (AudioType)20);
			yield return request.SendWebRequest();
			if ((int)request.result == 1)
			{
				AudioClip clip = DownloadHandlerAudioClip.GetContent(request);
				callback(clip);
				Logger.LogInfo((object)("✅ Loaded " + resourceName));
			}
			else
			{
				Logger.LogError((object)("❌ Failed to load " + resourceName + ": " + request.error));
			}
		}

		public void PlayComingInHot()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)comingInHotClip != (Object)null)
			{
				AudioSource val = new GameObject("LocalAudio").AddComponent<AudioSource>();
				val.clip = comingInHotClip;
				val.spatialBlend = 0f;
				val.volume = 1f;
				val.Play();
				Object.Destroy((Object)(object)((Component)val).gameObject, comingInHotClip.length);
			}
		}

		public void PlayComingInHotAt(Vector3 position)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)comingInHotClip == (Object)null)
			{
				Logger.LogError((object)"❌ Hot.wav is null.");
				return;
			}
			Logger.LogWarning((object)"\ud83d\udd25 Hot.wav triggered!");
			Logger.LogWarning((object)Environment.StackTrace);
			GameObject val = new GameObject("HotAudio");
			val.transform.position = position;
			AudioSource val2 = val.AddComponent<AudioSource>();
			val2.clip = comingInHotClip;
			val2.volume = 1f;
			val2.spatialBlend = 0f;
			val2.Play();
			val.AddComponent<AutoDestroyAudio>().duration = comingInHotClip.length + 0.5f;
		}

		private void EnsureAudioListenerExists()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			if ((Object)(object)Object.FindObjectOfType<AudioListener>() == (Object)null)
			{
				Logger.LogWarning((object)"⚠\ufe0f No AudioListener found — creating fallback AudioListener.");
				GameObject val = new GameObject("FallbackAudioListener");
				val.AddComponent<AudioListener>();
				Object.DontDestroyOnLoad((Object)(object)val);
				Logger.LogInfo((object)"✅ Fallback AudioListener created.");
			}
			else
			{
				Logger.LogInfo((object)"\ud83c\udfa7 AudioListener found in scene.");
			}
		}
	}
	public class AudioUpdate : MonoBehaviour
	{
		public Plugin? Plugin;

		private void Update()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown((KeyCode)116))
			{
				MyAudioMod.Plugin.Logger.LogInfo((object)"\ud83d\udd34 Manual test: playing Hot.wav in 2D");
				Plugin?.PlayComingInHotAt(Vector3.zero);
			}
		}
	}
	[HarmonyPatch(typeof(Sound), "Play")]
	public static class DebugSoundPlay
	{
		[HarmonyPrefix]
		public static void Prefix(Sound __instance)
		{
			if (__instance.Sounds != null && __instance.Sounds.Length != 0)
			{
				AudioClip obj = __instance.Sounds[0];
				string text = ((obj != null) ? ((Object)obj).name : null) ?? "null";
				Plugin.Logger.LogInfo((object)("\ud83d\udd0a Sound.Play called: " + text));
			}
		}
	}
	[HarmonyPatch(typeof(Sound), "Play")]
	public static class TumbleSoundInterceptPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(Sound __instance, Vector3 position)
		{
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			StackTrace stackTrace = new StackTrace();
			for (int i = 0; i < stackTrace.FrameCount; i++)
			{
				MethodBase methodBase = stackTrace.GetFrame(i)?.GetMethod();
				if (!(methodBase?.DeclaringType?.Name == "TumbleUI") || !(methodBase.Name == "Update"))
				{
					continue;
				}
				Type declaringType = methodBase.DeclaringType;
				FieldInfo fieldInfo = AccessTools.Field(declaringType, "canExitSound");
				StackFrame[] frames = stackTrace.GetFrames();
				foreach (StackFrame stackFrame in frames)
				{
					if (!(stackFrame?.GetMethod()?.DeclaringType == declaringType))
					{
						continue;
					}
					object value = Traverse.Create(stackFrame.GetMethod().IsStatic ? null : stackFrame.GetMethod()?.ReflectedType).Field("this").GetValue();
					if (value != null)
					{
						object? value2 = fieldInfo.GetValue(value);
						Sound val = (Sound)((value2 is Sound) ? value2 : null);
						if (val == __instance)
						{
							Plugin.Logger.LogInfo((object)"\ud83c\udfaf Intercepted canExitSound from TumbleUI. Playing ComingInHot.wav instead.");
							Plugin.Instance?.PlayComingInHotAt(position);
							return false;
						}
					}
				}
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Sound), "Play")]
	public static class TumbleSoundReplacePatch
	{
		[HarmonyPrefix]
		public static bool Prefix(Sound __instance, Vector3 position)
		{
			AudioClip value = Traverse.Create((object)__instance).Field("clip").GetValue<AudioClip>();
			if ((Object)(object)value != (Object)null && ((Object)value).name.Contains("player tumble can exit"))
			{
				Plugin.Logger.LogInfo((object)("\ud83d\ude45 Suppressing tumble exit sound: " + ((Object)value).name));
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	public static class TumbleUI_Update_Patch
	{
		private static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("TumbleUI");
			if (type == null)
			{
				Plugin.Logger.LogError((object)"❌ TumbleUI type not found!");
				return null;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "Update", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				Plugin.Logger.LogError((object)"❌ TumbleUI.Update not found!");
				return null;
			}
			Plugin.Logger.LogInfo((object)("✅ Patch target resolved: " + methodInfo.DeclaringType.FullName + "." + methodInfo.Name));
			return methodInfo;
		}

		private static bool Prefix(object __instance)
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			Type type = __instance.GetType();
			FieldInfo fieldInfo = AccessTools.Field(type, "canExit");
			FieldInfo fieldInfo2 = AccessTools.Field(type, "canExitPrevious");
			if (fieldInfo == null || fieldInfo2 == null)
			{
				Plugin.Logger.LogWarning((object)"❌ TumbleUI fields not found.");
				return true;
			}
			bool flag = (bool)fieldInfo.GetValue(__instance);
			bool flag2 = (bool)fieldInfo2.GetValue(__instance);
			if (flag && !flag2)
			{
				Plugin.Logger.LogInfo((object)"\ud83d\udca5 Detected tumble exit — playing ComingInHot.wav");
				Plugin.Instance.PlayComingInHotAt(((Component)(MonoBehaviour)__instance).transform.position);
			}
			return true;
		}
	}
}
namespace MyRepoMod
{
	[HarmonyPatch(typeof(PlayerController))]
	internal static class ExamplePlayerControllerPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("Update")]
		private static void Update_Prefix(PlayerController __instance)
		{
			MyRepoMod.Logger.LogDebug((object)$"{__instance} Update Prefix");
		}

		[HarmonyPostfix]
		[HarmonyPatch("Update")]
		private static void Update_Postfix(PlayerController __instance)
		{
			MyRepoMod.Logger.LogDebug((object)$"{__instance} Update Postfix");
		}
	}
	[BepInPlugin("YourName.MyRepoMod", "MyRepoMod", "1.0")]
	public class MyRepoMod : BaseUnityPlugin
	{
		internal static MyRepoMod Instance { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; set; }

		private void Awake()
		{
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Patch();
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
		}

		internal void Patch()
		{
			//IL_001a: 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_0021: Expected O, but got Unknown
			//IL_0026: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				Harmony val2 = val;
				Harmony = val;
			}
			Harmony.PatchAll();
		}

		internal void Unpatch()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void Update()
		{
		}
	}
}