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);
}
}
}