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 Dracula Flow Headman v1.0.0
plugins/HeadmanVoiceLines/HeadmanVoiceLines.dll
Decompiled 7 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Threading; using BepInEx; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.Networking; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("HeadmanVoiceLines")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("HP")] [assembly: AssemblyProduct("HeadmanVoiceLines")] [assembly: AssemblyCopyright("Copyright © HP 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("2c9dd7b1-80e1-471e-878b-e0cd7c5f897a")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace HeadmanVoiceLines; [BepInPlugin("com.yourname.headmanvoicelines", "Headman Voice Lines", "2.2.0")] public class HeadmanVoiceLinesPlugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static List<AudioClip> VoiceLines = new List<AudioClip>(); internal static List<AudioClip> AttackLines = new List<AudioClip>(); internal static string PluginFolder; internal static AssetBundle ModelBundle; internal static GameObject CustomModelPrefab; internal static float MinTimeBetweenLines = 5f; internal static float MaxTimeBetweenLines = 13f; internal static float VoiceVolume = 0.7f; private void Awake() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; PluginFolder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); LoadVoiceLines(); LoadModelBundle(); Harmony val = new Harmony("com.yourname.headmanvoicelines"); val.PatchAll(); Log.LogInfo((object)"Headman Voice Lines + Model Swap plugin started!"); } private void LoadModelBundle() { string text = Path.Combine(PluginFolder, "headmanmod"); if (!File.Exists(text)) { Log.LogWarning((object)("Asset bundle not found at: " + text)); return; } ModelBundle = AssetBundle.LoadFromFile(text); if ((Object)(object)ModelBundle == (Object)null) { Log.LogError((object)"Failed to load asset bundle!"); return; } GameObject[] array = ModelBundle.LoadAllAssets<GameObject>(); Log.LogInfo((object)$"Found {array.Length} GameObjects in bundle"); if (array.Length != 0) { CustomModelPrefab = array[0]; Log.LogInfo((object)("Loaded model: " + ((Object)CustomModelPrefab).name)); } else { Log.LogError((object)"No GameObjects found in asset bundle!"); } } private void LoadVoiceLines() { string path = Path.Combine(PluginFolder, "VoiceLines"); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); return; } string[] files = Directory.GetFiles(path, "*.wav"); foreach (string text in files) { AudioClip val = LoadWavFile(text); if ((Object)(object)val != (Object)null) { VoiceLines.Add(val); Log.LogInfo((object)("Loaded voice line: " + Path.GetFileName(text))); } } string[] files2 = Directory.GetFiles(path, "*.ogg"); foreach (string text2 in files2) { AudioClip val2 = LoadOggFile(text2); if ((Object)(object)val2 != (Object)null) { VoiceLines.Add(val2); Log.LogInfo((object)("Loaded voice line: " + Path.GetFileName(text2))); } } Log.LogInfo((object)$"Loaded {VoiceLines.Count} voice line(s)."); string path2 = Path.Combine(PluginFolder, "AttackLines"); if (!Directory.Exists(path2)) { Directory.CreateDirectory(path2); Log.LogInfo((object)"Created AttackLines folder (add .wav files for chase voice lines)"); return; } string[] files3 = Directory.GetFiles(path2, "*.wav"); foreach (string text3 in files3) { AudioClip val3 = LoadWavFile(text3); if ((Object)(object)val3 != (Object)null) { AttackLines.Add(val3); Log.LogInfo((object)("Loaded attack line: " + Path.GetFileName(text3))); } } string[] files4 = Directory.GetFiles(path2, "*.ogg"); foreach (string text4 in files4) { AudioClip val4 = LoadOggFile(text4); if ((Object)(object)val4 != (Object)null) { AttackLines.Add(val4); Log.LogInfo((object)("Loaded attack line: " + Path.GetFileName(text4))); } } Log.LogInfo((object)$"Loaded {AttackLines.Count} attack line(s)."); } private AudioClip LoadWavFile(string filePath) { try { byte[] array = File.ReadAllBytes(filePath); int num = BitConverter.ToInt16(array, 22); int num2 = BitConverter.ToInt32(array, 24); int num3 = BitConverter.ToInt16(array, 34); int num4; for (int i = 12; i < array.Length - 8; i += 8 + num4) { string @string = Encoding.ASCII.GetString(array, i, 4); num4 = BitConverter.ToInt32(array, i + 4); if (!(@string == "data")) { continue; } i += 8; int num5 = num4 / (num3 / 8) / num; float[] array2 = new float[num5 * num]; switch (num3) { case 16: { for (int k = 0; k < array2.Length && i + k * 2 + 1 < array.Length; k++) { short num6 = BitConverter.ToInt16(array, i + k * 2); array2[k] = (float)num6 / 32768f; } break; } case 8: { for (int j = 0; j < array2.Length && i + j < array.Length; j++) { array2[j] = (float)(array[i + j] - 128) / 128f; } break; } } AudioClip val = AudioClip.Create(Path.GetFileNameWithoutExtension(filePath), num5, num, num2, false); val.SetData(array2, 0); return val; } return null; } catch (Exception ex) { Log.LogError((object)("Error loading WAV: " + ex.Message)); return null; } } private AudioClip LoadOggFile(string filePath) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Invalid comparison between Unknown and I4 try { string text = "file:///" + filePath.Replace("\\", "/"); UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(text, (AudioType)14); audioClip.SendWebRequest(); while (!audioClip.isDone) { Thread.Sleep(10); } if ((int)audioClip.result == 1) { AudioClip content = DownloadHandlerAudioClip.GetContent(audioClip); ((Object)content).name = Path.GetFileNameWithoutExtension(filePath); return content; } return null; } catch (Exception ex) { Log.LogError((object)("Error loading OGG: " + ex.Message)); return null; } } } public static class PluginInfo { public const string PLUGIN_GUID = "com.yourname.headmanvoicelines"; public const string PLUGIN_NAME = "Headman Voice Lines"; public const string PLUGIN_VERSION = "2.2.0"; } public class HeadmanVoiceLinePlayer : MonoBehaviour { private AudioSource voiceSource; private float nextLineTime; private object enemyObject; private PropertyInfo currentStateProp; private FieldInfo _currentStateField; private Type enemyStateType; private object stateRoaming; private object stateSneak; private object stateChase; private object stateChaseSlow; private object stateChaseBegin; private object stateChaseEnd; private object stateLookUnder; private object stateInvestigate; private bool isSetup = false; private Transform jawTransform; private float jawTalkAngle = 20f; private float jawBiteAngle = 40f; private float jawSpeed = 8f; private float jawTalkSpeed = 12f; private float currentJawAngle = 0f; private object previousState = null; private object playerHealthObj; private FieldInfo playerHealthField; private PropertyInfo playerHealthProp; private float lastKnownHealth = -1f; private float biteSnapTime = 0f; private float biteSnapDuration = 0.5f; private void Start() { voiceSource = ((Component)this).gameObject.AddComponent<AudioSource>(); voiceSource.spatialBlend = 1f; voiceSource.rolloffMode = (AudioRolloffMode)1; voiceSource.minDistance = 2f; voiceSource.maxDistance = 30f; voiceSource.volume = HeadmanVoiceLinesPlugin.VoiceVolume; voiceSource.playOnAwake = false; SetupReflection(); SwapModel(); ResetTimer(); } private void SwapModel() { //IL_05b5: Unknown result type (might be due to invalid IL or missing references) //IL_05ba: Unknown result type (might be due to invalid IL or missing references) //IL_05cf: Unknown result type (might be due to invalid IL or missing references) //IL_070c: Unknown result type (might be due to invalid IL or missing references) //IL_0713: Unknown result type (might be due to invalid IL or missing references) //IL_0728: Unknown result type (might be due to invalid IL or missing references) //IL_073a: Unknown result type (might be due to invalid IL or missing references) //IL_074c: Unknown result type (might be due to invalid IL or missing references) //IL_12c6: Unknown result type (might be due to invalid IL or missing references) //IL_12ec: Unknown result type (might be due to invalid IL or missing references) //IL_0922: Unknown result type (might be due to invalid IL or missing references) //IL_0929: Expected O, but got Unknown //IL_0929: Unknown result type (might be due to invalid IL or missing references) //IL_092e: Unknown result type (might be due to invalid IL or missing references) //IL_13ae: Unknown result type (might be due to invalid IL or missing references) //IL_13ba: Unknown result type (might be due to invalid IL or missing references) //IL_13bf: Unknown result type (might be due to invalid IL or missing references) //IL_13c3: Unknown result type (might be due to invalid IL or missing references) //IL_09a5: Unknown result type (might be due to invalid IL or missing references) //IL_095c: Unknown result type (might be due to invalid IL or missing references) //IL_0961: Unknown result type (might be due to invalid IL or missing references) //IL_0d97: Unknown result type (might be due to invalid IL or missing references) //IL_0d9c: Unknown result type (might be due to invalid IL or missing references) //IL_0da0: Unknown result type (might be due to invalid IL or missing references) //IL_0dac: Unknown result type (might be due to invalid IL or missing references) //IL_0db1: Unknown result type (might be due to invalid IL or missing references) //IL_0db5: Unknown result type (might be due to invalid IL or missing references) //IL_0c6e: Unknown result type (might be due to invalid IL or missing references) //IL_0c74: Expected O, but got Unknown //IL_0c88: Unknown result type (might be due to invalid IL or missing references) //IL_09c1: Unknown result type (might be due to invalid IL or missing references) //IL_0984: Unknown result type (might be due to invalid IL or missing references) //IL_0989: Unknown result type (might be due to invalid IL or missing references) //IL_10c7: Unknown result type (might be due to invalid IL or missing references) //IL_10cc: Unknown result type (might be due to invalid IL or missing references) //IL_10d0: Unknown result type (might be due to invalid IL or missing references) //IL_10d5: Unknown result type (might be due to invalid IL or missing references) //IL_09e2: Unknown result type (might be due to invalid IL or missing references) //IL_10fd: Unknown result type (might be due to invalid IL or missing references) //IL_1111: Unknown result type (might be due to invalid IL or missing references) //IL_1116: Unknown result type (might be due to invalid IL or missing references) //IL_112d: Unknown result type (might be due to invalid IL or missing references) //IL_1132: Unknown result type (might be due to invalid IL or missing references) //IL_1136: Unknown result type (might be due to invalid IL or missing references) //IL_1142: Unknown result type (might be due to invalid IL or missing references) //IL_1147: Unknown result type (might be due to invalid IL or missing references) //IL_114b: Unknown result type (might be due to invalid IL or missing references) //IL_11d8: Unknown result type (might be due to invalid IL or missing references) //IL_11dd: Unknown result type (might be due to invalid IL or missing references) //IL_11e1: Unknown result type (might be due to invalid IL or missing references) //IL_11ed: Unknown result type (might be due to invalid IL or missing references) //IL_11f2: Unknown result type (might be due to invalid IL or missing references) //IL_11f6: Unknown result type (might be due to invalid IL or missing references) //IL_1243: Unknown result type (might be due to invalid IL or missing references) //IL_1248: Unknown result type (might be due to invalid IL or missing references) //IL_124c: Unknown result type (might be due to invalid IL or missing references) //IL_1258: Unknown result type (might be due to invalid IL or missing references) //IL_125d: Unknown result type (might be due to invalid IL or missing references) //IL_1261: Unknown result type (might be due to invalid IL or missing references) //IL_0e6a: Unknown result type (might be due to invalid IL or missing references) //IL_0e6f: Unknown result type (might be due to invalid IL or missing references) //IL_0ed0: Unknown result type (might be due to invalid IL or missing references) //IL_0edf: Unknown result type (might be due to invalid IL or missing references) //IL_0eee: Unknown result type (might be due to invalid IL or missing references) //IL_0efd: Unknown result type (might be due to invalid IL or missing references) //IL_0f0c: Unknown result type (might be due to invalid IL or missing references) //IL_0f1b: Unknown result type (might be due to invalid IL or missing references) //IL_0e85: Unknown result type (might be due to invalid IL or missing references) //IL_0e8b: Unknown result type (might be due to invalid IL or missing references) //IL_0e90: Unknown result type (might be due to invalid IL or missing references) //IL_0e95: Unknown result type (might be due to invalid IL or missing references) //IL_0e97: Unknown result type (might be due to invalid IL or missing references) //IL_0e9d: Unknown result type (might be due to invalid IL or missing references) //IL_0ea2: Unknown result type (might be due to invalid IL or missing references) //IL_0ea7: Unknown result type (might be due to invalid IL or missing references) //IL_106b: Unknown result type (might be due to invalid IL or missing references) //IL_1070: Unknown result type (might be due to invalid IL or missing references) //IL_1074: Unknown result type (might be due to invalid IL or missing references) //IL_1080: Unknown result type (might be due to invalid IL or missing references) //IL_1085: Unknown result type (might be due to invalid IL or missing references) //IL_1089: Unknown result type (might be due to invalid IL or missing references) //IL_0bc2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)HeadmanVoiceLinesPlugin.CustomModelPrefab == (Object)null) { HeadmanVoiceLinesPlugin.Log.LogWarning((object)"No custom model to swap!"); return; } try { Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { type = assembly.GetType("EnemyHeadController"); if (type != null) { break; } } if (type == null) { return; } Component val = ((Component)this).GetComponent(type); if ((Object)(object)val == (Object)null) { val = ((Component)this).GetComponentInParent(type); } if ((Object)(object)val == (Object)null) { return; } Transform val2 = val.transform; while ((Object)(object)val2.parent != (Object)null) { Type type2 = null; Assembly[] assemblies2 = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly2 in assemblies2) { type2 = assembly2.GetType("EnemyParent"); if (type2 != null) { break; } } if (type2 != null && (Object)(object)((Component)val2).GetComponent(type2) != (Object)null) { break; } val2 = val2.parent; } HeadmanVoiceLinesPlugin.Log.LogInfo((object)("Head enemy root: " + ((Object)val2).name)); Renderer[] componentsInChildren = ((Component)val2).GetComponentsInChildren<Renderer>(true); HeadmanVoiceLinesPlugin.Log.LogInfo((object)$"Found {componentsInChildren.Length} renderers on Head enemy"); Material val3 = null; Shader val4 = null; Texture2D val5 = null; HashSet<string> hashSet = new HashSet<string>(); int num = -1; Renderer[] array = componentsInChildren; foreach (Renderer val6 in array) { if ((Object)(object)val6.sharedMaterial != (Object)null && (Object)(object)val6.sharedMaterial.shader != (Object)null) { string name = ((Object)val6.sharedMaterial.shader).name; hashSet.Add(name); HeadmanVoiceLinesPlugin.Log.LogInfo((object)$" Renderer '{((Object)((Component)val6).gameObject).name}' shader='{name}' layer={((Component)val6).gameObject.layer} type={((object)val6).GetType().Name}"); } } HeadmanVoiceLinesPlugin.Log.LogInfo((object)("All shaders used by Head enemy: " + string.Join(", ", hashSet))); string[] array2 = new string[3] { "Hurtable/Hurtable", "Hurtable/Hurtable Alpha Clip", "Standard" }; string[] array3 = array2; foreach (string text in array3) { if ((Object)(object)val4 != (Object)null) { break; } Renderer[] array4 = componentsInChildren; foreach (Renderer val7 in array4) { if ((Object)(object)val7.sharedMaterial != (Object)null && (Object)(object)val7.sharedMaterial.shader != (Object)null && ((Object)val7.sharedMaterial.shader).name == text && !(((object)val7).GetType().Name == "ParticleSystemRenderer") && !(((Object)((Component)val7).gameObject).name == "Debug")) { val4 = val7.sharedMaterial.shader; val3 = val7.sharedMaterial; num = ((Component)val7).gameObject.layer; if ((Object)(object)val7.sharedMaterial.mainTexture != (Object)null) { Texture mainTexture = val7.sharedMaterial.mainTexture; val5 = (Texture2D)(object)((mainTexture is Texture2D) ? mainTexture : null); } HeadmanVoiceLinesPlugin.Log.LogInfo((object)$"STOLEN shader: '{((Object)val4).name}' from renderer '{((Object)((Component)val7).gameObject).name}' layer={num} (preferred match)"); break; } } } if ((Object)(object)val4 == (Object)null) { Renderer[] array5 = componentsInChildren; foreach (Renderer val8 in array5) { if (!(((object)val8).GetType().Name == "ParticleSystemRenderer") && !((Object)(object)val8.sharedMaterial == (Object)null) && !((Object)(object)val8.sharedMaterial.shader == (Object)null) && !((Object)val8.sharedMaterial.shader).name.Contains("Particle")) { val4 = val8.sharedMaterial.shader; val3 = val8.sharedMaterial; num = ((Component)val8).gameObject.layer; if ((Object)(object)val8.sharedMaterial.mainTexture != (Object)null) { Texture mainTexture2 = val8.sharedMaterial.mainTexture; val5 = (Texture2D)(object)((mainTexture2 is Texture2D) ? mainTexture2 : null); } HeadmanVoiceLinesPlugin.Log.LogInfo((object)("STOLEN shader: '" + ((Object)val4).name + "' from renderer '" + ((Object)((Component)val8).gameObject).name + "' (fallback non-particle)")); break; } } } if ((Object)(object)val4 != (Object)null) { HeadmanVoiceLinesPlugin.Log.LogInfo((object)(" Material: '" + ((Object)val3).name + "'")); HeadmanVoiceLinesPlugin.Log.LogInfo((object)$" Layer: {num}"); for (int num2 = 0; num2 < val4.GetPropertyCount(); num2++) { string propertyName = val4.GetPropertyName(num2); ShaderPropertyType propertyType = val4.GetPropertyType(num2); HeadmanVoiceLinesPlugin.Log.LogInfo((object)$" Shader prop [{num2}]: '{propertyName}' type={propertyType}"); } } else { HeadmanVoiceLinesPlugin.Log.LogWarning((object)"Could not find any suitable non-particle shader!"); } Renderer[] array6 = componentsInChildren; foreach (Renderer val9 in array6) { val9.enabled = false; } HeadmanVoiceLinesPlugin.Log.LogInfo((object)"Disabled all original Head renderers"); Transform val10 = null; Transform[] componentsInChildren2 = ((Component)val2).GetComponentsInChildren<Transform>(true); Transform[] array7 = componentsInChildren2; foreach (Transform val11 in array7) { if (((Object)val11).name == "Mesh" && (Object)(object)val11.parent != (Object)null && ((Object)val11.parent).name == "Enable") { val10 = val11; break; } } if ((Object)(object)val10 == (Object)null) { val10 = val.transform; HeadmanVoiceLinesPlugin.Log.LogInfo((object)"Mesh transform not found, attaching to controller"); } else { HeadmanVoiceLinesPlugin.Log.LogInfo((object)("Attaching to Mesh transform: " + ((Object)val10).name)); } GameObject val12 = Object.Instantiate<GameObject>(HeadmanVoiceLinesPlugin.CustomModelPrefab, val10.position, val10.rotation, val10); val12.transform.localPosition = Vector3.zero; val12.transform.localRotation = Quaternion.identity; val12.transform.localScale = Vector3.one; int num6 = (val12.layer = ((num >= 0) ? num : ((Component)val2).gameObject.layer)); Transform[] componentsInChildren3 = val12.GetComponentsInChildren<Transform>(true); foreach (Transform val13 in componentsInChildren3) { ((Component)val13).gameObject.layer = num6; } HeadmanVoiceLinesPlugin.Log.LogInfo((object)$"Set custom model layer to {num6} (headEnemyRoot layer={((Component)val2).gameObject.layer})"); Renderer[] componentsInChildren4 = val12.GetComponentsInChildren<Renderer>(true); HeadmanVoiceLinesPlugin.Log.LogInfo((object)$"Custom model has {componentsInChildren4.Length} renderers"); Texture2D val14 = null; if ((Object)(object)HeadmanVoiceLinesPlugin.ModelBundle != (Object)null) { Texture2D[] array8 = HeadmanVoiceLinesPlugin.ModelBundle.LoadAllAssets<Texture2D>(); HeadmanVoiceLinesPlugin.Log.LogInfo((object)$"Found {array8.Length} textures in bundle"); Texture2D[] array9 = array8; foreach (Texture2D val15 in array9) { HeadmanVoiceLinesPlugin.Log.LogInfo((object)$" Bundle texture: '{((Object)val15).name}' ({((Texture)val15).width}x{((Texture)val15).height})"); if ((Object)(object)val14 == (Object)null) { val14 = val15; } } } Renderer[] array10 = componentsInChildren4; Vector3 val20 = default(Vector3); Vector3 val21 = default(Vector3); foreach (Renderer val16 in array10) { val16.enabled = true; ((Component)val16).gameObject.SetActive(true); int num10 = ((num >= 0) ? num : ((Component)val2).gameObject.layer); ((Component)val16).gameObject.layer = num10; Material[] materials = val16.materials; for (int num11 = 0; num11 < materials.Length; num11++) { if ((Object)(object)val4 != (Object)null) { Material val17 = new Material(val4); Color val18 = Color.white; if ((Object)(object)materials[num11] != (Object)null) { if (materials[num11].HasProperty("_Color")) { val18 = materials[num11].color; } else if (materials[num11].HasProperty("_BaseColor")) { val18 = materials[num11].GetColor("_BaseColor"); } } if (val17.HasProperty("_AlbedoColor")) { val17.SetColor("_AlbedoColor", val18); } if (val17.HasProperty("_Color")) { val17.color = val18; } if (val17.HasProperty("_BaseColor")) { val17.SetColor("_BaseColor", val18); } if ((Object)(object)val14 != (Object)null) { if (val17.HasProperty("_AlbedoTexture")) { val17.SetTexture("_AlbedoTexture", (Texture)(object)val14); } if (val17.HasProperty("_MainTex")) { val17.SetTexture("_MainTex", (Texture)(object)val14); } if (val17.HasProperty("_BaseMap")) { val17.SetTexture("_BaseMap", (Texture)(object)val14); } if (val17.HasProperty("_BaseColorMap")) { val17.SetTexture("_BaseColorMap", (Texture)(object)val14); } } if (val17.HasProperty("_Mode")) { val17.SetFloat("_Mode", 0f); } if (val17.HasProperty("_SrcBlend")) { val17.SetFloat("_SrcBlend", 1f); } if (val17.HasProperty("_DstBlend")) { val17.SetFloat("_DstBlend", 0f); } if (val17.HasProperty("_ZWrite")) { val17.SetFloat("_ZWrite", 1f); } val17.renderQueue = -1; if (val17.HasProperty("_ColorOverlayAmount")) { val17.SetFloat("_ColorOverlayAmount", 0f); } if (val17.HasProperty("_Smoothness")) { val17.SetFloat("_Smoothness", 0.3f); } if (val17.HasProperty("_Metallic")) { val17.SetFloat("_Metallic", 0f); } materials[num11] = val17; HeadmanVoiceLinesPlugin.Log.LogInfo((object)$" Applied shader '{((Object)val4).name}' to material {num11} on '{((Object)((Component)val16).gameObject).name}' color={val18} layer={num10}"); continue; } HeadmanVoiceLinesPlugin.Log.LogWarning((object)"No stolen shader available! Trying fallbacks..."); string[] array11 = new string[8] { "Standard", "HDRP/Lit", "HDRP/Unlit", "Universal Render Pipeline/Lit", "Universal Render Pipeline/Unlit", "Unlit/Color", "Unlit/Texture", "Sprites/Default" }; string[] array12 = array11; foreach (string text2 in array12) { Shader val19 = Shader.Find(text2); if ((Object)(object)val19 != (Object)null) { materials[num11] = new Material(val19); materials[num11].color = new Color(0.79f, 0.66f, 0.57f); HeadmanVoiceLinesPlugin.Log.LogInfo((object)(" Using fallback shader: " + text2)); break; } } } val16.materials = materials; HeadmanVoiceLinesPlugin.Log.LogInfo((object)$" Enabled renderer: {((object)val16).GetType().Name} on '{((Object)((Component)val16).gameObject).name}' layer={((Component)val16).gameObject.layer}"); MeshFilter component = ((Component)val16).GetComponent<MeshFilter>(); Bounds bounds; if ((Object)(object)component != (Object)null && (Object)(object)component.mesh != (Object)null) { Mesh mesh = component.mesh; HeadmanVoiceLinesPlugin.Log.LogInfo((object)$" MESH DIAG: vertices={mesh.vertexCount} subMeshCount={mesh.subMeshCount} isReadable={mesh.isReadable}"); ManualLogSource log = HeadmanVoiceLinesPlugin.Log; bounds = mesh.bounds; object arg = ((Bounds)(ref bounds)).center; bounds = mesh.bounds; log.LogInfo((object)$" MESH DIAG: bounds center={arg} size={((Bounds)(ref bounds)).size}"); if (mesh.isReadable) { Vector3[] vertices = mesh.vertices; int[] triangles = mesh.triangles; Vector2[] uv = mesh.uv; Vector3[] normals = mesh.normals; HeadmanVoiceLinesPlugin.Log.LogInfo((object)$" MESH DIAG: tris={triangles.Length / 3} uvs={uv.Length} normals={normals.Length}"); ((Vector3)(ref val20))..ctor(float.MaxValue, float.MaxValue, float.MaxValue); ((Vector3)(ref val21))..ctor(float.MinValue, float.MinValue, float.MinValue); int num13 = 0; for (int num14 = 0; num14 < vertices.Length; num14++) { if (vertices[num14] == Vector3.zero) { num13++; } val20 = Vector3.Min(val20, vertices[num14]); val21 = Vector3.Max(val21, vertices[num14]); } HeadmanVoiceLinesPlugin.Log.LogInfo((object)$" VERTEX DIAG: min=({val20.x:F4},{val20.y:F4},{val20.z:F4}) max=({val21.x:F4},{val21.y:F4},{val21.z:F4})"); HeadmanVoiceLinesPlugin.Log.LogInfo((object)$" VERTEX DIAG: zeroVerts={num13}/{vertices.Length}"); for (int num15 = 0; num15 < Mathf.Min(5, vertices.Length); num15++) { HeadmanVoiceLinesPlugin.Log.LogInfo((object)$" VERTEX[{num15}]: ({vertices[num15].x:F4},{vertices[num15].y:F4},{vertices[num15].z:F4})"); } for (int num16 = 0; num16 < Mathf.Min(9, triangles.Length); num16 += 3) { HeadmanVoiceLinesPlugin.Log.LogInfo((object)$" TRI[{num16 / 3}]: {triangles[num16]},{triangles[num16 + 1]},{triangles[num16 + 2]}"); } mesh.RecalculateBounds(); ManualLogSource log2 = HeadmanVoiceLinesPlugin.Log; bounds = mesh.bounds; object arg2 = ((Bounds)(ref bounds)).center; bounds = mesh.bounds; log2.LogInfo((object)$" MESH DIAG: Recalculated bounds center={arg2} size={((Bounds)(ref bounds)).size}"); if (normals.Length == 0) { mesh.RecalculateNormals(); HeadmanVoiceLinesPlugin.Log.LogInfo((object)" MESH DIAG: Recalculated normals"); } } bounds = mesh.bounds; Vector3 size = ((Bounds)(ref bounds)).size; if (((Vector3)(ref size)).magnitude < 0.01f) { mesh.bounds = new Bounds(new Vector3(0f, 0.017f, 0f), new Vector3(0.1f, 0.1f, 0.1f)); ManualLogSource log3 = HeadmanVoiceLinesPlugin.Log; bounds = mesh.bounds; object arg3 = ((Bounds)(ref bounds)).center; bounds = mesh.bounds; log3.LogInfo((object)$" MESH DIAG: Forced bounds center={arg3} size={((Bounds)(ref bounds)).size}"); } } else { SkinnedMeshRenderer val22 = (SkinnedMeshRenderer)(object)((val16 is SkinnedMeshRenderer) ? val16 : null); if ((Object)(object)val22 != (Object)null && (Object)(object)val22.sharedMesh != (Object)null) { Mesh sharedMesh = val22.sharedMesh; HeadmanVoiceLinesPlugin.Log.LogInfo((object)$" SKINNED MESH DIAG: vertices={sharedMesh.vertexCount} triangles={sharedMesh.triangles.Length / 3}"); ManualLogSource log4 = HeadmanVoiceLinesPlugin.Log; bounds = sharedMesh.bounds; object arg4 = ((Bounds)(ref bounds)).center; bounds = sharedMesh.bounds; log4.LogInfo((object)$" SKINNED MESH DIAG: bounds center={arg4} size={((Bounds)(ref bounds)).size}"); } else { HeadmanVoiceLinesPlugin.Log.LogWarning((object)(" MESH DIAG: No MeshFilter or mesh found on '" + ((Object)((Component)val16).gameObject).name + "'!")); } } ManualLogSource log5 = HeadmanVoiceLinesPlugin.Log; bounds = val16.bounds; object arg5 = ((Bounds)(ref bounds)).center; bounds = val16.bounds; log5.LogInfo((object)$" RENDERER bounds: center={arg5} size={((Bounds)(ref bounds)).size}"); } HeadmanVoiceLinesPlugin.Log.LogInfo((object)$"Custom model active: {val12.activeSelf}, activeInHierarchy: {val12.activeInHierarchy}"); HeadmanVoiceLinesPlugin.Log.LogInfo((object)$"Custom model position: {val12.transform.position}"); HeadmanVoiceLinesPlugin.Log.LogInfo((object)$"Custom model worldScale: {val12.transform.lossyScale}"); Transform val23 = val12.transform; while ((Object)(object)val23 != (Object)null) { HeadmanVoiceLinesPlugin.Log.LogInfo((object)$" HIERARCHY: '{((Object)val23).name}' active={((Component)val23).gameObject.activeSelf} layer={((Component)val23).gameObject.layer}"); val23 = val23.parent; } Transform[] componentsInChildren5 = val12.GetComponentsInChildren<Transform>(true); foreach (Transform val24 in componentsInChildren5) { if (((Object)val24).name == "Head_Jaw") { jawTransform = val24; ManualLogSource log6 = HeadmanVoiceLinesPlugin.Log; string name2 = ((Object)val24).name; object arg6 = val24.localPosition; Quaternion localRotation = val24.localRotation; log6.LogInfo((object)$"Found jaw transform: '{name2}' localPos={arg6} localRot={((Quaternion)(ref localRotation)).eulerAngles}"); break; } } if ((Object)(object)jawTransform == (Object)null) { HeadmanVoiceLinesPlugin.Log.LogWarning((object)"Head_Jaw transform not found! Jaw animation won't work."); } HeadmanVoiceLinesPlugin.Log.LogInfo((object)"Model swap complete!"); } catch (Exception ex) { HeadmanVoiceLinesPlugin.Log.LogError((object)("Error swapping model: " + ex.Message)); HeadmanVoiceLinesPlugin.Log.LogError((object)("Stack trace: " + ex.StackTrace)); } } private void SetupReflection() { try { Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { type = assembly.GetType("Enemy"); if (type != null) { break; } } if (type == null) { return; } Type type2 = null; Assembly[] assemblies2 = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly2 in assemblies2) { type2 = assembly2.GetType("EnemyHeadController"); if (type2 != null) { break; } } if (type2 == null) { return; } Component val = ((Component)this).GetComponentInParent(type2); if ((Object)(object)val == (Object)null) { val = ((Component)this).GetComponent(type2); } if ((Object)(object)val == (Object)null) { return; } FieldInfo field = type2.GetField("Enemy", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { return; } enemyObject = field.GetValue(val); if (enemyObject == null) { return; } currentStateProp = type.GetProperty("CurrentState", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (currentStateProp == null) { _currentStateField = type.GetField("CurrentState", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } Assembly[] assemblies3 = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly3 in assemblies3) { enemyStateType = assembly3.GetType("EnemyState"); if (enemyStateType != null) { break; } } if (enemyStateType == null) { return; } stateRoaming = Enum.Parse(enemyStateType, "Roaming"); stateSneak = Enum.Parse(enemyStateType, "Sneak"); stateChase = Enum.Parse(enemyStateType, "Chase"); stateChaseSlow = Enum.Parse(enemyStateType, "ChaseSlow"); stateChaseBegin = Enum.Parse(enemyStateType, "ChaseBegin"); stateLookUnder = Enum.Parse(enemyStateType, "LookUnder"); try { stateChaseEnd = Enum.Parse(enemyStateType, "ChaseEnd"); } catch { stateChaseEnd = null; } try { stateInvestigate = Enum.Parse(enemyStateType, "Investigate"); } catch { stateInvestigate = null; } try { Type type3 = null; Assembly[] assemblies4 = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly4 in assemblies4) { type3 = assembly4.GetType("PlayerHealth"); if (type3 != null) { break; } } if (type3 != null) { Object obj3 = Object.FindObjectOfType(type3); Component val2 = (Component)(object)((obj3 is Component) ? obj3 : null); if ((Object)(object)val2 != (Object)null) { playerHealthObj = val2; playerHealthField = type3.GetField("health", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (playerHealthField == null) { playerHealthField = type3.GetField("Health", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } if (playerHealthField == null) { playerHealthField = type3.GetField("hp", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } if (playerHealthField == null) { playerHealthProp = type3.GetProperty("health", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (playerHealthProp == null) { playerHealthProp = type3.GetProperty("Health", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } } HeadmanVoiceLinesPlugin.Log.LogInfo((object)("Found PlayerHealth: field=" + playerHealthField?.Name + " prop=" + playerHealthProp?.Name)); } } } catch (Exception ex) { HeadmanVoiceLinesPlugin.Log.LogWarning((object)("Could not find player health: " + ex.Message)); } isSetup = true; } catch (Exception ex2) { HeadmanVoiceLinesPlugin.Log.LogError((object)("Reflection setup error: " + ex2.Message)); } } private object GetCurrentState() { if (enemyObject == null) { return null; } try { if (currentStateProp != null) { return currentStateProp.GetValue(enemyObject, null); } if (_currentStateField != null) { return _currentStateField.GetValue(enemyObject); } } catch { } return null; } private void Update() { //IL_0251: Unknown result type (might be due to invalid IL or missing references) if (!isSetup || HeadmanVoiceLinesPlugin.VoiceLines.Count == 0) { return; } object currentState = GetCurrentState(); bool flag = (Object)(object)voiceSource != (Object)null && voiceSource.isPlaying; bool flag2 = false; if (currentState != null) { flag2 = currentState.Equals(stateChase) || currentState.Equals(stateChaseSlow) || currentState.Equals(stateChaseBegin); } if (currentState != null && previousState != null && currentState.Equals(stateChaseBegin) && !previousState.Equals(stateChaseBegin) && HeadmanVoiceLinesPlugin.AttackLines.Count > 0) { PlayRandomAttackLine(); } previousState = currentState; if (!flag && Time.time >= nextLineTime) { if (IsInMovingState()) { if (flag2 && HeadmanVoiceLinesPlugin.AttackLines.Count > 0) { PlayRandomAttackLine(); } else { PlayRandomLine(); } } ResetTimer(); } if ((Object)(object)jawTransform != (Object)null) { bool flag3 = false; if (currentState != null && stateChaseEnd != null) { flag3 = currentState.Equals(stateChaseEnd); } bool flag4 = (Object)(object)voiceSource != (Object)null && voiceSource.isPlaying; if (flag3) { currentJawAngle = 0f; } else if (flag2) { float num = jawBiteAngle; currentJawAngle = Mathf.Lerp(currentJawAngle, num, Time.deltaTime * jawSpeed); } else if (flag4) { float num2 = (Mathf.Sin(Time.time * jawTalkSpeed) + 1f) * 0.5f; currentJawAngle = num2 * jawTalkAngle; } else { currentJawAngle = Mathf.Lerp(currentJawAngle, 0f, Time.deltaTime * jawSpeed); } jawTransform.localRotation = Quaternion.Euler(currentJawAngle, 0f, 0f); } } private bool IsInMovingState() { object currentState = GetCurrentState(); if (currentState == null) { return false; } try { bool flag = currentState.Equals(stateRoaming) || currentState.Equals(stateSneak) || currentState.Equals(stateChase) || currentState.Equals(stateChaseSlow) || currentState.Equals(stateChaseBegin) || currentState.Equals(stateLookUnder); if (stateInvestigate != null) { flag = flag || currentState.Equals(stateInvestigate); } return flag; } catch { return false; } } private void PlayRandomLine() { if (!((Object)(object)voiceSource == (Object)null) && HeadmanVoiceLinesPlugin.VoiceLines.Count != 0) { int index = Random.Range(0, HeadmanVoiceLinesPlugin.VoiceLines.Count); AudioClip clip = HeadmanVoiceLinesPlugin.VoiceLines[index]; voiceSource.clip = clip; voiceSource.pitch = 1f; voiceSource.Play(); } } private void PlayRandomAttackLine() { if (!((Object)(object)voiceSource == (Object)null) && HeadmanVoiceLinesPlugin.AttackLines.Count != 0) { int index = Random.Range(0, HeadmanVoiceLinesPlugin.AttackLines.Count); AudioClip clip = HeadmanVoiceLinesPlugin.AttackLines[index]; voiceSource.clip = clip; voiceSource.pitch = 1f; voiceSource.Play(); } } private void ResetTimer() { nextLineTime = Time.time + Random.Range(HeadmanVoiceLinesPlugin.MinTimeBetweenLines, HeadmanVoiceLinesPlugin.MaxTimeBetweenLines); } } [HarmonyPatch] public class EnemyHeadControllerAwakePatch { private static MethodBase TargetMethod() { Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { type = assembly.GetType("EnemyHeadController"); if (type != null) { break; } } if (type == null) { return null; } MethodInfo method = type.GetMethod("Awake", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { method = type.GetMethod("OnSpawn", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } return method; } private static void Postfix(object __instance) { try { Component val = (Component)((__instance is Component) ? __instance : null); if ((Object)(object)val != (Object)null && (Object)(object)val.gameObject.GetComponent<HeadmanVoiceLinePlayer>() == (Object)null) { val.gameObject.AddComponent<HeadmanVoiceLinePlayer>(); } } catch (Exception ex) { HeadmanVoiceLinesPlugin.Log.LogError((object)("Error in patch: " + ex.Message)); } } }