Decompiled source of TouhouSekibankiSpringManCoilHead v0.9.0

TouhouEnemyModels.dll

Decompiled 5 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;

[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("TouhouEnemyModels")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("A template for Lethal Company")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+a4bc3033c6e7539201fec8f6c242e3c4a65bb8b3")]
[assembly: AssemblyProduct("TouhouEnemyModels")]
[assembly: AssemblyTitle("TouhouEnemyModels")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TouhouEnemyModels
{
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "com.bean.TouhouEnemyModels";

		public const string PLUGIN_NAME = "TouhouEnemyModels";

		public const string PLUGIN_VERSION = "0.9.0";
	}
	[HarmonyPatch]
	internal class Patches
	{
		[HarmonyPatch(typeof(DeadBodyInfo), "Start")]
		internal class BodySpringPatch
		{
			private static void Postfix(DeadBodyInfo __instance)
			{
				//IL_00d4: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
				//IL_0147: Unknown result type (might be due to invalid IL or missing references)
				//IL_0160: Unknown result type (might be due to invalid IL or missing references)
				//IL_0179: Unknown result type (might be due to invalid IL or missing references)
				if (__instance == null || (Object)(object)TouhouEnemiesPlugin.sekiHeadVisuals == (Object)null || !TouhouEnemiesPlugin.EnableCoilHeadReplace.Value || !TouhouEnemiesPlugin.EnableBodyCoilReplace.Value)
				{
					return;
				}
				Rigidbody[] bodyParts = __instance.bodyParts;
				foreach (Rigidbody val in bodyParts)
				{
					if (((Object)val).name.Contains("Spring"))
					{
						Transform val2 = ((Component)val).transform.Find("spine.001/spine.002/spine.003/spine.004/SpringContainer");
						SkinnedMeshRenderer component = ((Component)val2.Find("Spring.001")).GetComponent<SkinnedMeshRenderer>();
						Transform val3 = val2.Find("SpringMetarig");
						if ((Object)(object)component != (Object)null)
						{
							((Renderer)component).enabled = false;
						}
						GameObject val4 = Object.Instantiate<GameObject>(TouhouEnemiesPlugin.sekiHeadVisuals);
						val4.transform.SetParent(val2);
						val4.transform.localPosition = Vector3.zero;
						val4.transform.localRotation = Quaternion.identity;
						val4.transform.localScale = Vector3.one;
						Transform val5 = val4.transform.Find("Head/Body");
						Transform val6 = val4.transform.Find("Head/SpringMetarig");
						val6.SetParent(val3.parent, true);
						((Component)val6).transform.localScale = ((Component)val3).transform.localScale;
						((Component)val6).transform.localRotation = ((Component)val3).transform.localRotation;
						((Component)val6).transform.localPosition = ((Component)val3).transform.localPosition;
						SkinnedMeshRenderer component2 = ((Component)val5).GetComponent<SkinnedMeshRenderer>();
						component2.rootBone = val6;
						((Object)val6).name = "SpringMetarig";
						TouhouEnemiesPlugin.Instance.AddLog("Spring model changed");
					}
				}
			}
		}

		[HarmonyPatch(typeof(EnemyAI), "Start")]
		internal class EnemyAIPatch
		{
			private static void Prefix(EnemyAI __instance)
			{
				//IL_0130: Unknown result type (might be due to invalid IL or missing references)
				//IL_0142: Unknown result type (might be due to invalid IL or missing references)
				//IL_0154: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
				//IL_021b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0225: Expected O, but got Unknown
				//IL_03be: Unknown result type (might be due to invalid IL or missing references)
				//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
				//IL_045f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0478: Unknown result type (might be due to invalid IL or missing references)
				//IL_0491: Unknown result type (might be due to invalid IL or missing references)
				//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
				//IL_0501: Expected O, but got Unknown
				if (!(__instance is SpringManAI))
				{
					NutcrackerEnemyAI val = (NutcrackerEnemyAI)(object)((__instance is NutcrackerEnemyAI) ? __instance : null);
					if (val != null && (Object)(object)TouhouEnemiesPlugin.satoriVisuals != (Object)null && TouhouEnemiesPlugin.EnableNutcrackerReplace.Value)
					{
						Animator componentInChildren = ((Component)val).GetComponentInChildren<Animator>();
						RuntimeAnimatorController runtimeAnimatorController = componentInChildren.runtimeAnimatorController;
						Transform val2 = ((Component)val).transform.Find("MeshContainer");
						object obj;
						if (val2 == null)
						{
							obj = null;
						}
						else
						{
							Transform obj2 = val2.Find("LOD0");
							obj = ((obj2 != null) ? ((Component)obj2).GetComponent<SkinnedMeshRenderer>() : null);
						}
						SkinnedMeshRenderer val3 = (SkinnedMeshRenderer)obj;
						object obj3;
						if (val2 == null)
						{
							obj3 = null;
						}
						else
						{
							Transform obj4 = val2.Find("LOD1");
							obj3 = ((obj4 != null) ? ((Component)obj4).GetComponent<SkinnedMeshRenderer>() : null);
						}
						SkinnedMeshRenderer val4 = (SkinnedMeshRenderer)obj3;
						object obj5;
						if (val2 == null)
						{
							obj5 = null;
						}
						else
						{
							Transform obj6 = val2.Find("AnimContainer/metarig/spinecontainer/GunAndArmsContainer/GunPoint/GunPointWithOffset/TestShotgun");
							obj5 = ((obj6 != null) ? ((Component)obj6).GetComponent<MeshRenderer>() : null);
						}
						MeshRenderer val5 = (MeshRenderer)obj5;
						object obj7;
						if (val2 == null)
						{
							obj7 = null;
						}
						else
						{
							Transform obj8 = val2.Find("AnimContainer/metarig/spinecontainer/GunAndArmsContainer/GunPoint/GunPointWithOffset/TestShotgun/GunBarrel");
							obj7 = ((obj8 != null) ? ((Component)obj8).GetComponent<MeshRenderer>() : null);
						}
						MeshRenderer val6 = (MeshRenderer)obj7;
						if ((Object)(object)val3 != (Object)null)
						{
							((Renderer)val3).enabled = false;
						}
						if ((Object)(object)val4 != (Object)null)
						{
							((Renderer)val4).enabled = false;
						}
						if ((Object)(object)val5 != (Object)null)
						{
							((Renderer)val5).enabled = false;
						}
						if ((Object)(object)val6 != (Object)null)
						{
							((Renderer)val6).enabled = false;
						}
						Transform val7 = ((val2 != null) ? val2.Find("AnimContainer").Find("metarig") : null);
						if (!((Object)(object)val7 == (Object)null))
						{
							((Object)val7).name = "old-metarig";
							GameObject val8 = Object.Instantiate<GameObject>(TouhouEnemiesPlugin.satoriVisuals);
							val8.transform.SetParent(val2);
							val8.transform.localPosition = Vector3.zero;
							val8.transform.localRotation = Quaternion.identity;
							val8.transform.localScale = Vector3.one;
							Transform val9 = val8.transform.Find("MeshContainer/LOD0");
							Transform val10 = val8.transform.Find("MeshContainer/AnimContainer/metarig");
							val.torsoContainer = val8.transform.Find("MeshContainer/AnimContainer/metarig/spinecontainer");
							val.gunPoint = val8.transform.Find("MeshContainer/AnimContainer/metarig/spinecontainer/GunAndArmsContainer/GunPoint/GunPointWithOffset");
							val10.SetParent(val7.parent, true);
							((Component)val10).transform.localScale = ((Component)val7).transform.localScale;
							((Component)val10).transform.localRotation = ((Component)val7).transform.localRotation;
							((Component)val10).transform.localPosition = ((Component)val7).transform.localPosition;
							SkinnedMeshRenderer component = ((Component)val9).GetComponent<SkinnedMeshRenderer>();
							component.rootBone = val10;
							((Object)val10).name = "metarig";
							TouhouEnemiesPlugin.Instance.AddLog($"Nutcracker model changed. Torsor: {(Object)(object)val.torsoContainer != (Object)null}, GunPoint: {(Object)(object)val.gunPoint != (Object)null}");
							componentInChildren.runtimeAnimatorController = (RuntimeAnimatorController)new AnimatorOverrideController(runtimeAnimatorController);
							TouhouEnemiesPlugin.Instance.AddLog("The state of the animator reset");
						}
					}
				}
				else
				{
					if (!((Object)(object)TouhouEnemiesPlugin.sekiVisuals != (Object)null) || !TouhouEnemiesPlugin.EnableCoilHeadReplace.Value)
					{
						return;
					}
					Animator componentInChildren2 = ((Component)__instance).GetComponentInChildren<Animator>();
					RuntimeAnimatorController runtimeAnimatorController2 = componentInChildren2.runtimeAnimatorController;
					Transform val11 = ((Component)__instance).transform.Find("SpringManModel");
					Transform obj9 = ((val11 != null) ? val11.Find("Body") : null);
					SkinnedMeshRenderer val12 = ((obj9 != null) ? ((Component)obj9).GetComponent<SkinnedMeshRenderer>() : null);
					if ((Object)(object)val12 != (Object)null)
					{
						((Renderer)val12).enabled = false;
					}
					Transform obj10 = ((val11 != null) ? val11.Find("Head") : null);
					MeshRenderer val13 = ((obj10 != null) ? ((Component)obj10).GetComponent<MeshRenderer>() : null);
					Transform val14 = ((val11 != null) ? val11.Find("AnimContainer").Find("metarig") : null);
					if (!((Object)(object)val14 == (Object)null))
					{
						((Object)val14).name = "old-metarig";
						if ((Object)(object)val13 != (Object)null)
						{
							((Renderer)val13).enabled = false;
						}
						GameObject val15 = Object.Instantiate<GameObject>(TouhouEnemiesPlugin.sekiVisuals);
						val15.transform.SetParent(val11);
						val15.transform.localPosition = Vector3.zero;
						val15.transform.localRotation = Quaternion.identity;
						val15.transform.localScale = Vector3.one;
						Transform val16 = val15.transform.Find("SekibankiModel/Body");
						Transform val17 = val15.transform.Find("SekibankiModel/metarig");
						val17.SetParent(val14.parent, true);
						((Component)val17).transform.localScale = ((Component)val14).transform.localScale;
						((Component)val17).transform.localRotation = ((Component)val14).transform.localRotation;
						((Component)val17).transform.localPosition = new Vector3(0f, -0.27f, 0f);
						SkinnedMeshRenderer component2 = ((Component)val16).GetComponent<SkinnedMeshRenderer>();
						component2.rootBone = val17;
						((Object)val17).name = "metarig";
						TouhouEnemiesPlugin.Instance.AddLog("SpringMan model changed");
						componentInChildren2.runtimeAnimatorController = (RuntimeAnimatorController)new AnimatorOverrideController(runtimeAnimatorController2);
						TouhouEnemiesPlugin.Instance.AddLog("The state of the animator reset");
					}
				}
			}
		}

		[HarmonyPatch(typeof(SpringManAI), "SetAnimationGoClientRpc")]
		[HarmonyPostfix]
		[ClientRpc]
		public static void PlayWalkSounds(SpringManAI __instance)
		{
			if (TouhouEnemiesPlugin.EnableCoilHeadReplace.Value && TouhouEnemiesPlugin.EnableSekibankiTheme.Value && !((Object)(object)TouhouEnemiesPlugin.SekibankiTheme == (Object)null))
			{
				if ((Object)(object)((EnemyAI)__instance).creatureSFX.clip != (Object)(object)TouhouEnemiesPlugin.SekibankiTheme)
				{
					((EnemyAI)__instance).creatureSFX.clip = TouhouEnemiesPlugin.SekibankiTheme;
					((EnemyAI)__instance).creatureSFX.volume = 0.75f;
					((EnemyAI)__instance).creatureSFX.loop = true;
				}
				if (((EnemyAI)__instance).creatureSFX.isPlaying)
				{
					((EnemyAI)__instance).creatureSFX.UnPause();
				}
				else
				{
					((EnemyAI)__instance).creatureSFX.Play();
				}
				TouhouEnemiesPlugin.Instance.AddLog("Playing Sekibanki theme.");
				WalkieTalkie.TransmitOneShotAudio(((EnemyAI)__instance).creatureSFX, TouhouEnemiesPlugin.SekibankiTheme, 0.4f);
			}
		}

		[HarmonyPatch(typeof(SpringManAI), "SetAnimationStopClientRpc")]
		[HarmonyPostfix]
		[ClientRpc]
		public static void StopWalkSounds(SpringManAI __instance)
		{
			if (TouhouEnemiesPlugin.EnableCoilHeadReplace.Value && TouhouEnemiesPlugin.EnableSekibankiTheme.Value && !((Object)(object)TouhouEnemiesPlugin.SekibankiTheme == (Object)null) && ((EnemyAI)__instance).creatureSFX.isPlaying)
			{
				((EnemyAI)__instance).creatureSFX.Pause();
				TouhouEnemiesPlugin.Instance.AddLog("Stop playing Sekibanki theme.");
			}
		}

		[HarmonyPatch(typeof(NutcrackerEnemyAI), "Start")]
		[HarmonyPostfix]
		public static void ReplaceAudio(SpringManAI __instance)
		{
			if (TouhouEnemiesPlugin.EnableNutcrackerReplace.Value && TouhouEnemiesPlugin.EnableSatoriTheme.Value && !((Object)(object)TouhouEnemiesPlugin.SatoriTheme == (Object)null))
			{
				((EnemyAI)__instance).enemyBehaviourStates[2].VoiceClip = TouhouEnemiesPlugin.SatoriTheme;
				TouhouEnemiesPlugin.Instance.AddLog("Satori theme Loaded.");
			}
		}
	}
	[BepInPlugin("com.bean.TouhouEnemyModels", "TouhouEnemyModels", "0.9.0")]
	public class TouhouEnemiesPlugin : BaseUnityPlugin
	{
		public static TouhouEnemiesPlugin Instance;

		public static GameObject sekiVisuals;

		public static GameObject sekiHeadVisuals;

		public static GameObject satoriVisuals;

		internal static ConfigEntry<bool> EnableCoilHeadReplace;

		internal static ConfigEntry<bool> EnableBodyCoilReplace;

		internal static ConfigEntry<bool> EnableSekibankiTheme;

		public static AudioClip SekibankiTheme;

		internal static ConfigEntry<bool> EnableNutcrackerReplace;

		internal static ConfigEntry<bool> EnableSatoriTheme;

		public static AudioClip SatoriTheme;

		private void Awake()
		{
			Instance = this;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin TouhouEnemyModels is loaded!");
			EnableCoilHeadReplace = ((BaseUnityPlugin)this).Config.Bind<bool>("CoilHead", "EnableCoilHead", true, "Replace the model of Coil-Head to Sekibanki.");
			EnableBodyCoilReplace = ((BaseUnityPlugin)this).Config.Bind<bool>("CoilHead", "EnableDeadBodyCoil", true, "Replace the coil on the dead body to a head of Sekibanki.");
			EnableSekibankiTheme = ((BaseUnityPlugin)this).Config.Bind<bool>("CoilHead", "EnableSekibankiTheme", true, "Replace the step audio to Sekibanki theme music.");
			EnableNutcrackerReplace = ((BaseUnityPlugin)this).Config.Bind<bool>("Nutcracker", "EnableNutcracker", true, "Replace the model of Nutcracker to NutSatori.");
			EnableSatoriTheme = ((BaseUnityPlugin)this).Config.Bind<bool>("Nutcracker", "EnableSatoriTheme", true, "Replace the angry audio to Satori theme music.");
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
			try
			{
				AssetBundle val = AssetUtils.LoadAssetBundleFromResources("touhouenemies", typeof(TouhouEnemiesPlugin).Assembly);
				List<Renderer> list = new List<Renderer>();
				if (EnableCoilHeadReplace.Value)
				{
					sekiVisuals = val.LoadAsset<GameObject>("Sekibanki.prefab");
					list.AddRange(sekiVisuals.GetComponentsInChildren<Renderer>(true).ToList());
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"Load Sekibanki: {(Object)(object)sekiVisuals != (Object)null}");
					SekibankiTheme = val.LoadAsset<AudioClip>("SekibankiTheme.mp3");
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"Load SekibankiTheme: {(Object)(object)SekibankiTheme != (Object)null}");
					if (EnableBodyCoilReplace.Value)
					{
						sekiHeadVisuals = val.LoadAsset<GameObject>("SekibankiHead.prefab");
						((BaseUnityPlugin)this).Logger.LogInfo((object)$"Load SekibankiHead: {(Object)(object)sekiHeadVisuals != (Object)null}");
					}
				}
				if (EnableNutcrackerReplace.Value)
				{
					satoriVisuals = val.LoadAsset<GameObject>("NutSatori.prefab");
					list.AddRange(satoriVisuals.GetComponentsInChildren<Renderer>(true).ToList());
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"Load NutSatori: {(Object)(object)satoriVisuals != (Object)null}");
					SatoriTheme = val.LoadAsset<AudioClip>("SatoriTheme.mp3");
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"Load SatoriTheme: {(Object)(object)SatoriTheme != (Object)null}");
				}
				foreach (Renderer item in list)
				{
					((Component)item).gameObject.layer = LayerMask.NameToLayer("Enemies");
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Couldn't load asset bundle: " + ex.Message));
			}
		}

		public void AddLog(string info)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)info);
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "TouhouEnemyModels";

		public const string PLUGIN_NAME = "TouhouEnemyModels";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace Jotunn.Utils
{
	public static class AssetUtils
	{
		public const char AssetBundlePathSeparator = '$';

		public static Texture2D LoadTexture(string texturePath, bool relativePath = true)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			string text = texturePath;
			if (relativePath)
			{
				text = Path.Combine(Paths.PluginPath, texturePath);
			}
			if (!File.Exists(text))
			{
				return null;
			}
			if (!text.EndsWith(".png") && !text.EndsWith(".jpg"))
			{
				throw new Exception("LoadTexture can only load png or jpg textures");
			}
			byte[] array = File.ReadAllBytes(text);
			Texture2D val = new Texture2D(2, 2);
			val.LoadRawTextureData(array);
			return val;
		}

		public static Sprite LoadSpriteFromFile(string spritePath)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = LoadTexture(spritePath);
			if ((Object)(object)val != (Object)null)
			{
				return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), default(Vector2), 100f);
			}
			return null;
		}

		public static AssetBundle LoadAssetBundle(string bundlePath)
		{
			string text = Path.Combine(Paths.PluginPath, bundlePath);
			if (!File.Exists(text))
			{
				return null;
			}
			return AssetBundle.LoadFromFile(text);
		}

		public static AssetBundle LoadAssetBundleFromResources(string bundleName, Assembly resourceAssembly)
		{
			if (resourceAssembly == null)
			{
				throw new ArgumentNullException("Parameter resourceAssembly can not be null.");
			}
			string text = null;
			try
			{
				text = resourceAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(bundleName));
			}
			catch (Exception)
			{
			}
			if (text == null)
			{
				Debug.LogError((object)("AssetBundle " + bundleName + " not found in assembly manifest"));
				return null;
			}
			AssetBundle result;
			using (Stream stream = resourceAssembly.GetManifestResourceStream(text))
			{
				result = AssetBundle.LoadFromStream(stream);
			}
			return result;
		}

		public static string LoadText(string path)
		{
			string text = Path.Combine(Paths.PluginPath, path);
			if (!File.Exists(text))
			{
				Debug.LogError((object)("Error, failed to load contents from non-existant path: $" + text));
				return null;
			}
			return File.ReadAllText(text);
		}

		public static Sprite LoadSprite(string assetPath)
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			string text = Path.Combine(Paths.PluginPath, assetPath);
			if (!File.Exists(text))
			{
				return null;
			}
			if (text.Contains('$'.ToString()))
			{
				string[] array = text.Split('$');
				string text2 = array[0];
				string text3 = array[1];
				AssetBundle val = AssetBundle.LoadFromFile(text2);
				Sprite result = val.LoadAsset<Sprite>(text3);
				val.Unload(false);
				return result;
			}
			Texture2D val2 = LoadTexture(text, relativePath: false);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				return null;
			}
			return Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), Vector2.zero);
		}
	}
}