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 TouhouSekibankiSpringManCoilHead v0.9.0
TouhouEnemyModels.dll
Decompiled 2 years agousing 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); } } }