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 TheEavesdropper v0.6.2
BepInEx/plugins/TheEavesdropper/Eavesdropper.dll
Decompiled 4 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using Dissonance; using Eavesdropper.Art; using Eavesdropper.Core; using GameNetcodeStuff; using HarmonyLib; using LethalLib.Modules; using Microsoft.CodeAnalysis; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Eavesdropper")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.6.2.0")] [assembly: AssemblyInformationalVersion("0.6.2")] [assembly: AssemblyProduct("Eavesdropper")] [assembly: AssemblyTitle("Eavesdropper")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.6.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [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 Eavesdropper { internal sealed class AdvancedVisual { private sealed class Take { internal float Fps; internal Vector3[][] Positions; internal Quaternion[][] Rotations; } internal Mesh Mesh; internal Material[] Materials = Array.Empty<Material>(); private readonly Dictionary<string, Take> takes = new Dictionary<string, Take>(); private static string ReadName(BinaryReader r) { int num = r.ReadInt32(); if (num < 0 || num > 256) { throw new InvalidDataException("Invalid asset name"); } return Encoding.UTF8.GetString(r.ReadBytes(num)); } private static int Count(BinaryReader r, int max) { int num = r.ReadInt32(); if (num < 0 || num > max) { throw new InvalidDataException("Invalid asset count"); } return num; } private static float Float(BinaryReader r) { float num = r.ReadSingle(); if (!float.IsFinite(num)) { throw new InvalidDataException("Nonfinite visual data"); } return num; } internal static AdvancedVisual? Load() { string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location), "eavesdropper-visual"); if (!File.Exists(Path.Combine(text, "eavesdropper.mesh"))) { return null; } AdvancedVisual advancedVisual = new AdvancedVisual(); try { advancedVisual.Read(text); Plugin.Instance.Log("Loaded Blender visual and " + advancedVisual.takes.Count + " animation takes."); return advancedVisual; } catch (Exception ex) { Plugin.Instance.Error("Blender visual rejected; using built-in fallback. " + ex.Message); return null; } } private void Read(string folder) { //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Expected O, but got Unknown //IL_03b0: Unknown result type (might be due to invalid IL or missing references) //IL_03b5: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_049d: Unknown result type (might be due to invalid IL or missing references) //IL_04a2: Unknown result type (might be due to invalid IL or missing references) //IL_04c2: Expected O, but got Unknown //IL_04f9: Unknown result type (might be due to invalid IL or missing references) //IL_04e3: Unknown result type (might be due to invalid IL or missing references) //IL_0538: Unknown result type (might be due to invalid IL or missing references) //IL_0522: Unknown result type (might be due to invalid IL or missing references) Creature model = CreatureRig.Model; List<Vector3> list = new List<Vector3>(); List<Vector3> list2 = new List<Vector3>(); List<Vector2> list3 = new List<Vector2>(); List<BoneWeight> list4 = new List<BoneWeight>(); List<int>[] array = new List<int>[5]; for (int i = 0; i < 5; i++) { array[i] = new List<int>(); } int[] array2; using (BinaryReader binaryReader = new BinaryReader(File.OpenRead(Path.Combine(folder, "eavesdropper.mesh")))) { if (Encoding.ASCII.GetString(binaryReader.ReadBytes(8)) != "EAVMESH1") { throw new InvalidDataException("Mesh version"); } int num = Count(binaryReader, 100); if (num != model.Joints.Count) { throw new InvalidDataException("Rig size"); } array2 = new int[num]; HashSet<int> hashSet = new HashSet<int>(); for (int j = 0; j < num; j++) { array2[j] = model.Bone(ReadName(binaryReader)); if (array2[j] < 0 || !hashSet.Add(array2[j])) { throw new InvalidDataException("Rig names"); } } int num2 = Count(binaryReader, 300); for (int k = 0; k < num2; k++) { ReadName(binaryReader); int num3 = Count(binaryReader, 4); int num4 = Count(binaryReader, 300000); int num5 = Count(binaryReader, 900000); int count = list.Count; if (count + num4 > 400000 || num5 % 3 != 0) { throw new InvalidDataException("Mesh budget"); } for (int l = 0; l < num4; l++) { list.Add(new Vector3(Float(binaryReader), Float(binaryReader), Float(binaryReader))); list2.Add(new Vector3(Float(binaryReader), Float(binaryReader), Float(binaryReader))); list3.Add(new Vector2(Float(binaryReader), Float(binaryReader))); int[] array3 = new int[4]; float[] array4 = new float[4]; float num6 = 0f; for (int m = 0; m < 4; m++) { int num7 = Count(binaryReader, num - 1); array3[m] = array2[num7]; array4[m] = Float(binaryReader); if (array4[m] < 0f) { throw new InvalidDataException("Weight"); } num6 += array4[m]; } if (Math.Abs(num6 - 1f) > 0.01f) { throw new InvalidDataException("Weight sum"); } BoneWeight item = default(BoneWeight); ((BoneWeight)(ref item)).boneIndex0 = array3[0]; ((BoneWeight)(ref item)).boneIndex1 = array3[1]; ((BoneWeight)(ref item)).boneIndex2 = array3[2]; ((BoneWeight)(ref item)).boneIndex3 = array3[3]; ((BoneWeight)(ref item)).weight0 = array4[0]; ((BoneWeight)(ref item)).weight1 = array4[1]; ((BoneWeight)(ref item)).weight2 = array4[2]; ((BoneWeight)(ref item)).weight3 = array4[3]; list4.Add(item); } for (int n = 0; n < num5; n++) { array[num3].Add(count + Count(binaryReader, num4 - 1)); } } } Mesh = new Mesh { name = "Blender armored Eavesdropper", indexFormat = (IndexFormat)1 }; Mesh.SetVertices(list); Mesh.SetNormals(list2); Mesh.SetUVs(0, list3); Mesh.boneWeights = list4.ToArray(); Matrix4x4[] array5 = (Matrix4x4[])(object)new Matrix4x4[array2.Length]; for (int num8 = 0; num8 < array5.Length; num8++) { Vector3 position = model.Joints[num8].Position; array5[num8] = Matrix4x4.Translate(new Vector3(0f - position.X, 0f - position.Y, 0f - position.Z)); } Mesh.bindposes = array5; Mesh.subMeshCount = 5; for (int num9 = 0; num9 < 5; num9++) { Mesh.SetTriangles(array[num9], num9); } Mesh.RecalculateBounds(); Mesh.RecalculateTangents(); Shader val = Shader.Find("HDRP/Lit") ?? Shader.Find("Standard"); if ((Object)(object)val == (Object)null) { throw new InvalidDataException("Missing lit shader"); } string[] names = new string[5] { "Armor", "Sinew", "EarMembrane", "Ivory", "Mouth" }; Materials = (Material[])(object)new Material[5]; int num10; for (num10 = 0; num10 < 5; num10++) { Material val2 = new Material(val) { name = "Eavesdropper " + names[num10] }; Materials[num10] = val2; val2.SetColor("_BaseColor", (Color)((num10 == 4) ? new Color(0.012f, 0.006f, 0.007f) : Color.white)); if (val2.HasProperty("_Color")) { val2.SetColor("_Color", (Color)((num10 == 4) ? new Color(0.012f, 0.006f, 0.007f) : Color.white)); } val2.SetFloat("_Smoothness", (num10 == 0) ? 0.22f : 0.4f); val2.SetFloat("_DoubleSidedEnable", 1f); val2.SetFloat("_CullMode", 0f); val2.SetFloat("_CullModeForward", 0f); val2.EnableKeyword("_DOUBLESIDED_ON"); if (num10 != 4) { Texture2D val3 = LoadTexture("_BaseColor", linear: false); val2.SetTexture("_BaseColorMap", (Texture)(object)val3); if (val2.HasProperty("_MainTex")) { val2.SetTexture("_MainTex", (Texture)(object)val3); } Texture2D val4 = LoadTexture("_Normal", linear: true); val2.SetTexture("_NormalMap", (Texture)(object)val4); if (val2.HasProperty("_BumpMap")) { val2.SetTexture("_BumpMap", (Texture)(object)val4); } val2.EnableKeyword("_NORMALMAP"); val2.EnableKeyword("_NORMALMAP_TANGENT_SPACE"); val2.SetFloat("_NormalScale", 0.45f); Texture2D val5 = LoadTexture("_Mask", linear: true); val2.SetTexture("_MaskMap", (Texture)(object)val5); val2.EnableKeyword("_MASKMAP"); val2.SetFloat("_SmoothnessRemapMin", 0f); val2.SetFloat("_SmoothnessRemapMax", 1f); } } using (BinaryReader binaryReader2 = new BinaryReader(File.OpenRead(Path.Combine(folder, "eavesdropper.anim")))) { if (Encoding.ASCII.GetString(binaryReader2.ReadBytes(8)) != "EAVANIM1" || Count(binaryReader2, 100) != array2.Length) { throw new InvalidDataException("Animation rig/version"); } int num11 = Count(binaryReader2, 64); for (int num12 = 0; num12 < num11; num12++) { string key = ReadName(binaryReader2); int num13 = Count(binaryReader2, 1000); float num14 = Float(binaryReader2); if (num13 < 2 || num14 < 1f || num14 > 120f) { throw new InvalidDataException("Animation rate"); } Take take = new Take { Fps = num14, Positions = new Vector3[num13][], Rotations = new Quaternion[num13][] }; for (int num15 = 0; num15 < num13; num15++) { take.Positions[num15] = new Vector3[array2.Length]; take.Rotations[num15] = new Quaternion[array2.Length]; for (int num16 = 0; num16 < array2.Length; num16++) { take.Positions[num15][array2[num16]] = new Vector3(Float(binaryReader2), Float(binaryReader2), Float(binaryReader2)); Quaternion value = new Quaternion(Float(binaryReader2), Float(binaryReader2), Float(binaryReader2), Float(binaryReader2)); if (value.LengthSquared() < 0.5f) { throw new InvalidDataException("Invalid joint rotation"); } take.Rotations[num15][array2[num16]] = Quaternion.Normalize(value); } } takes.Add(key, take); } } if (!takes.ContainsKey("DoorBash")) { throw new InvalidDataException("Missing DoorBash clip"); } string[] clips = Creature.Clips; foreach (string text in clips) { if (!takes.ContainsKey(text)) { throw new InvalidDataException("Missing clip " + text); } } Texture2D LoadTexture(string suffix, bool linear) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_0067: Expected O, but got Unknown Texture2D val6 = new Texture2D(2, 2, (TextureFormat)4, true, linear) { name = names[num10] + suffix, wrapMode = (TextureWrapMode)0 }; if (!ImageConversion.LoadImage(val6, File.ReadAllBytes(Path.Combine(folder, names[num10] + suffix + ".png")), true)) { throw new InvalidDataException("Invalid texture"); } return val6; } } internal void Sample(string clip, float time, Vector3[] p, Quaternion[] q) { Take take = takes[clip]; float num = (float)(take.Positions.Length - 1) / take.Fps; bool flag; switch (clip) { case "Listen": case "Sprint": case "Wander": case "Dormant": case "Retreat": case "Stunned": case "Investigate": case "DoorCrawl": flag = true; break; default: flag = false; break; } float num2 = (flag ? Mathf.Repeat(Mathf.Max(0f, time), num) : Mathf.Clamp(time, 0f, num)) * take.Fps; int num3 = Mathf.Min((int)num2, take.Positions.Length - 1); int num4 = Mathf.Min(num3 + 1, take.Positions.Length - 1); float amount = num2 - (float)num3; for (int i = 0; i < p.Length; i++) { p[i] = Vector3.Lerp(take.Positions[num3][i], take.Positions[num4][i], amount); q[i] = Quaternion.Slerp(take.Rotations[num3][i], take.Rotations[num4][i], amount); } } } internal static class ConfigMenu { private static bool pending; private static bool oldLook; private static bool oldMove; private static bool oldSpecial; private static bool oldCursor; private static CursorLockMode oldLock; private static PlayerControllerB? player; private static Vector2 scroll; private static string search = ""; private static string message = ""; private static readonly Dictionary<ConfigEntryBase, string> drafts = new Dictionary<ConfigEntryBase, string>(); internal static bool Open { get; private set; } private static bool Authority { get { if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsListening) { return NetworkManager.Singleton.IsServer; } return true; } } private static bool Editable(ConfigEntryBase e) { if (!Authority) { return e.Definition.Section == "Accessibility"; } return true; } private static string Text(object o) { return Convert.ToString(o, CultureInfo.InvariantCulture) ?? ""; } private static void Load() { drafts.Clear(); foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in from p in (IEnumerable<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)((BaseUnityPlugin)Plugin.Instance).Config orderby p.Key.Section, p.Key.Key select p) { drafts[item.Value] = Text(item.Value.BoxedValue); } } internal static void Close() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) if (Open) { Open = false; if ((Object)(object)player != (Object)null) { player.disableLookInput = oldLook; player.disableMoveInput = oldMove; player.inSpecialMenu = oldSpecial; } Cursor.visible = oldCursor; Cursor.lockState = oldLock; player = null; } } internal static void Tick() { //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) if (pending && !EavesdropperAI.Live.Any((EavesdropperAI e) => e.DisplayState == Mode.Attacking || e.DisplayState == Mode.Echolocating)) { Configuration.BindAll(((BaseUnityPlugin)Plugin.Instance).Config, Plugin.Settings); foreach (EavesdropperAI item in EavesdropperAI.Live) { if ((Object)(object)((EnemyAI)item).creatureSFX != (Object)null) { ((EnemyAI)item).creatureSFX.maxDistance = Mathf.Max(35f, Plugin.Settings.EchoRange + 4f); } if ((Object)(object)((EnemyAI)item).creatureVoice != (Object)null) { ((EnemyAI)item).creatureVoice.maxDistance = Mathf.Max(35f, Plugin.Settings.EchoRange + 4f); } } pending = false; message = "Saved and applied. Spawn rarity requires a game restart; initial agitation affects new enemies."; } if (Open && (Object)(object)player != (Object)null && (player.isPlayerDead || (Object)(object)GameNetworkManager.Instance?.localPlayerController != (Object)(object)player)) { Close(); } if (Open && (Object)(object)player == (Object)null) { Keyboard current2 = Keyboard.current; if (current2 != null && ((ButtonControl)current2.escapeKey).wasPressedThisFrame) { Close(); return; } } Keyboard current3 = Keyboard.current; if (current3 == null || !((ButtonControl)current3.f6Key).wasPressedThisFrame) { return; } if (Open) { Close(); return; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val != (Object)null) || (!val.isPlayerDead && !val.isTypingChat && !val.inTerminalMenu && !val.inSpecialMenu && (!((Object)(object)val.quickMenuManager != (Object)null) || !val.quickMenuManager.isMenuOpen))) { player = val; if ((Object)(object)val != (Object)null) { oldLook = val.disableLookInput; oldMove = val.disableMoveInput; oldSpecial = val.inSpecialMenu; } oldCursor = Cursor.visible; oldLock = Cursor.lockState; Load(); search = ""; scroll = Vector2.zero; Open = true; message = "Edit values, then Save & apply. Closing discards unsaved edits. The game continues while this screen is open."; HoldInput(); } } internal static void HoldInput() { if (Open) { if ((Object)(object)player != (Object)null) { player.disableLookInput = true; player.disableMoveInput = true; player.inSpecialMenu = true; } Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; } } private static void Save() { Dictionary<ConfigEntryBase, object> parsed = new Dictionary<ConfigEntryBase, object>(); foreach (KeyValuePair<ConfigEntryBase, string> draft in drafts) { if (Editable(draft.Key)) { if (!ConfigInput.Parse(draft.Value, draft.Key.SettingType, out object value) || (draft.Key.Description.AcceptableValues != null && !draft.Key.Description.AcceptableValues.IsValid(value))) { message = "Invalid value: " + draft.Key.Definition.Key + ". Use the displayed range and a decimal point."; return; } parsed[draft.Key] = value; } } if (Authority && !ConfigInput.Tiers(Value("AgitationInitial"), Value("AgitationIrritatedThreshold"), Value("AgitationAngryThreshold"), Value("AgitationEnragedThreshold"), Value("AgitationMaximum"))) { message = "Require 0 < Irritated < Angry < Enraged < Maximum, and Initial between zero and Maximum."; return; } ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config; bool saveOnConfigSet = config.SaveOnConfigSet; Dictionary<ConfigEntryBase, object> dictionary = parsed.ToDictionary<KeyValuePair<ConfigEntryBase, object>, ConfigEntryBase, object>((KeyValuePair<ConfigEntryBase, object> p) => p.Key, (KeyValuePair<ConfigEntryBase, object> p) => p.Key.BoxedValue); try { config.SaveOnConfigSet = false; foreach (KeyValuePair<ConfigEntryBase, object> item in parsed) { if (!object.Equals(item.Key.BoxedValue, item.Value)) { item.Key.BoxedValue = item.Value; } } config.Save(); pending = Authority; message = (pending ? "Saved. Gameplay changes apply when active scans and attacks finish." : "Local accessibility settings saved."); Load(); Plugin.Instance.Log("F6 configuration saved; gameplay apply queued=" + pending); } catch (Exception ex) { foreach (KeyValuePair<ConfigEntryBase, object> item2 in dictionary) { item2.Key.BoxedValue = item2.Value; } message = "Could not save configuration: " + ex.Message; Plugin.Instance.Error(message); } finally { config.SaveOnConfigSet = saveOnConfigSet; } float Value(string name) { ConfigEntryBase val = drafts.Keys.First((ConfigEntryBase e) => e.Definition.Key == name); object value2; return Convert.ToSingle(parsed.TryGetValue(val, out value2) ? value2 : val.BoxedValue, CultureInfo.InvariantCulture); } } internal static void Draw() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_048d: Unknown result type (might be due to invalid IL or missing references) if (!Open) { return; } Matrix4x4 matrix = GUI.matrix; float num = Mathf.Min(1f, Mathf.Min((float)Screen.width / 980f, (float)Screen.height / 740f)); GUI.matrix = Matrix4x4.Scale(new Vector3(num, num, 1f)); float num2 = (float)Screen.width / num; float num3 = (float)Screen.height / num; GUI.Box(new Rect(0f, 0f, num2, num3), ""); GUILayout.BeginArea(new Rect((num2 - 940f) / 2f, (num3 - 700f) / 2f, 940f, 700f), GUI.skin.box); GUILayout.Label("THE EAVESDROPPER / CONFIGURATION / F6 or Esc to close", Array.Empty<GUILayoutOption>()); GUILayout.Label(Authority ? "Host settings • changes affect this host's creatures" : "Client • only local accessibility is editable. Other values are this PC's saved settings, not the host's values.", Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("Search", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) }); search = GUILayout.TextField(search, Array.Empty<GUILayoutOption>()); GUILayout.EndHorizontal(); scroll = GUILayout.BeginScrollView(scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(525f) }); string text = ""; ConfigEntryBase[] array = drafts.Keys.ToArray(); foreach (ConfigEntryBase val in array) { if (search.Length <= 0 || (val.Definition.Key + " " + val.Definition.Section + " " + val.Description.Description).IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0) { if (text != val.Definition.Section) { text = val.Definition.Section; GUILayout.Space(10f); GUILayout.Label("— " + text + " —", Array.Empty<GUILayoutOption>()); } bool enabled = GUI.enabled; GUI.enabled = Editable(val); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(val.Definition.Key, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(330f) }); if (val.SettingType == typeof(bool)) { drafts[val] = GUILayout.Toggle(bool.TryParse(drafts[val], out var result) && result, "Enabled", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(155f) }).ToString(); } else { drafts[val] = GUILayout.TextField(drafts[val], (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(155f) }); } if (GUILayout.Button("Default", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) })) { drafts[val] = Text(val.DefaultValue); } AcceptableValueBase acceptableValues = val.Description.AcceptableValues; GUILayout.Label(((acceptableValues != null) ? acceptableValues.ToDescriptionString().Replace("# ", "") : null) ?? "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(300f) }); GUILayout.EndHorizontal(); GUI.enabled = enabled; GUILayout.Label(val.Description.Description + ((val.Definition.Key == "Rarity") ? " RESTART REQUIRED." : ((val.Definition.Key == "AgitationInitial") ? " New enemies only." : "")), Array.Empty<GUILayoutOption>()); } } GUILayout.EndScrollView(); GUILayout.Label(message, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(50f) }); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Save & apply", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { Save(); } if (GUILayout.Button("Discard edits", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { Load(); message = "Unsaved edits discarded."; } if (GUILayout.Button("Close", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { Close(); } GUILayout.EndHorizontal(); GUILayout.EndArea(); GUI.matrix = matrix; } } [HarmonyPatch] internal static class ConfigInputGuard { private static IEnumerable<MethodBase> TargetMethods() { return from m in typeof(PlayerControllerB).GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where m.Name.EndsWith("_performed", StringComparison.Ordinal) && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == typeof(CallbackContext) select m; } private static bool Prefix(PlayerControllerB __instance, MethodBase __originalMethod) { if (!ConfigMenu.Open || (Object)(object)GameNetworkManager.Instance?.localPlayerController != (Object)(object)__instance) { return true; } if (__originalMethod.Name == "OpenMenu_performed") { ConfigMenu.Close(); } return false; } } internal static class Configuration { private static readonly HashSet<string> retired = new HashSet<string> { "FixationWarning", "NoiseHuntSeconds", "NoiseAgitationThreshold", "AgitationDecay", "DoorLungeSeconds", "EchoMotionThreshold", "EchoHuntSeconds", "EchoInterval", "LoudNoisesToHunt", "DistractionLock", "ListenSeconds" }; internal static void BindAll(ConfigFile file, Settings values) { //IL_0450: Unknown result type (might be due to invalid IL or missing references) //IL_045a: Expected O, but got Unknown //IL_05fd: Unknown result type (might be due to invalid IL or missing references) //IL_0607: Expected O, but got Unknown FieldInfo[] fields = typeof(Settings).GetFields(BindingFlags.Instance | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { if (retired.Contains(fieldInfo.Name)) { continue; } string text = ((fieldInfo.Name == "Damage") ? "Combat" : "Tuning"); string text2 = ((fieldInfo.Name == "EchoIntervalStirred") ? "EchoInterval" : fieldInfo.Name); string text3; switch (fieldInfo.Name) { case "NoiseRange": text3 = "Maximum ordinary hearing radius in metres (HearingRadius)."; break; case "VoiceRange": text3 = "Speech hearing range in metres, capped by NoiseRange (VoiceDetectionRange)."; break; case "ObstructionMultiplier": text3 = "Ordinary hearing attenuation per obstruction (OccludedHearingMultiplier)."; break; case "FixationSeconds": text3 = "Listening window in seconds (FixationWindowSeconds); any audible speaker may confirm pursuit."; break; case "CompactPursuitSpeed": text3 = "Maximum folded/crawling pursuit speed in meters per second. Tight turns still slow movement. Default 6.5; existing RushSpeed remains the upper limit."; break; case "EchoDoorMultiplier": text3 = "Range multiplier through an open doorway (EchoDoorwayRangeMultiplier)."; break; case "EchoMovementThreshold": text3 = "Body displacement in metres between chirps, not speed or camera rotation."; break; case "AttackWarning": text3 = "Stationary attack telegraph duration in seconds before a direction-locked leap."; break; case "EchoIntervalIrritated": case "EchoIntervalEnraged": case "EchoIntervalStirred": case "EchoIntervalAngry": text3 = "Minimum seconds between sound-led scans at this agitation tier. A fresh heard lead and arrival are required; this does not schedule periodic scans."; break; default: text3 = (fieldInfo.Name.Contains("Multiplier") ? "Dimensionless tier/baseline multiplier." : ((fieldInfo.Name.Contains("Range") || fieldInfo.Name == "HallwayCommitDistance") ? "Metres." : (fieldInfo.Name.Contains("Speed") ? "Metres per second." : ((fieldInfo.Name.Contains("Seconds") || fieldInfo.Name.Contains("Interval") || fieldInfo.Name == "DistractionCooldown" || fieldInfo.Name == "PathTimeout") ? "Seconds." : ((fieldInfo.Name.Contains("PerSecond") || fieldInfo.Name.Contains("PerVoiceSecond") || fieldInfo.Name.Contains("PerNoiseSecond")) ? "Agitation points per audible second." : (fieldInfo.Name.StartsWith("Agitation") ? "Agitation points; ordinary gains scale with audibility." : "Host-authoritative behavior tuning; see docs/CONFIGURATION.md.")))))); break; } string text4 = text3; if (fieldInfo.FieldType == typeof(bool)) { fieldInfo.SetValue(values, file.Bind<bool>(text, text2, (bool)fieldInfo.GetValue(values), text4).Value); } else if (fieldInfo.FieldType == typeof(int)) { int num = ((fieldInfo.Name == "Damage") ? 100 : 10); fieldInfo.SetValue(values, file.Bind<int>(text, text2, (int)fieldInfo.GetValue(values), new ConfigDescription(text4, (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, num), Array.Empty<object>())).Value); } else if (!(fieldInfo.FieldType != typeof(float))) { float num2 = 0f; float num3 = 10000f; if (fieldInfo.Name.Contains("Seconds") || fieldInfo.Name.Contains("Interval") || fieldInfo.Name == "AttackWarning" || fieldInfo.Name == "LungeSeconds" || fieldInfo.Name == "PathTimeout" || fieldInfo.Name == "DistractionCooldown") { num2 = 0.05f; } if (fieldInfo.Name.Contains("Range") || fieldInfo.Name.Contains("Speed")) { num2 = 0.1f; num3 = 80f; } if (fieldInfo.Name.Contains("Multiplier")) { num2 = 0.05f; num3 = ((fieldInfo.Name.Contains("Obstruction") || fieldInfo.Name.Contains("Door")) ? 1 : 3); } if (fieldInfo.Name == "AgitationMaximum") { num2 = 1f; } if (fieldInfo.Name == "EchoMovementThreshold") { num2 = 0.01f; num3 = 2f; } if (fieldInfo.Name == "EchoWarningSeconds") { num2 = 0.2f; num3 = 5f; } float num4 = (float)fieldInfo.GetValue(values); float num5 = file.Bind<float>(text, text2, num4, new ConfigDescription(text4, (AcceptableValueBase)(object)new AcceptableValueRange<float>(num2, num3), Array.Empty<object>())).Value; if (!float.IsFinite(num5)) { Plugin.Instance.Error($"Non-finite {text2}; using default {num4} for this session."); num5 = num4; } fieldInfo.SetValue(values, num5); } } float agitationMaximum = values.AgitationMaximum; if (!(values.AgitationIrritatedThreshold > 0f) || !(values.AgitationIrritatedThreshold < values.AgitationAngryThreshold) || !(values.AgitationAngryThreshold < values.AgitationEnragedThreshold) || !(values.AgitationEnragedThreshold < agitationMaximum)) { Plugin.Instance.Error("Agitation tier thresholds must be ascending and below AgitationMaximum. Using 20%, 45%, 75% of maximum for this session; saved entries unchanged."); values.AgitationIrritatedThreshold = agitationMaximum * 0.2f; values.AgitationAngryThreshold = agitationMaximum * 0.45f; values.AgitationEnragedThreshold = agitationMaximum * 0.75f; } values.AgitationInitial = Math.Clamp(values.AgitationInitial, 0f, agitationMaximum); } } public sealed class CreatureRig : MonoBehaviour { internal static readonly Creature Model = new Creature(); private static AdvancedVisual? advanced; private static bool checkedAsset; public Transform[] joints = Array.Empty<Transform>(); private readonly Vector3[] positions = new Vector3[Model.Joints.Count]; private readonly Quaternion[] rotations = new Quaternion[Model.Joints.Count]; internal static GameObject Build(Transform parent) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown //IL_014f: 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_015f: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Expected O, but got Unknown //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_046b: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("EavesdropperVisual"); val.transform.SetParent(parent, false); CreatureRig creatureRig = val.AddComponent<CreatureRig>(); creatureRig.joints = (Transform[])(object)new Transform[Model.Joints.Count]; for (int i = 0; i < creatureRig.joints.Length; i++) { Joint joint = Model.Joints[i]; GameObject val2 = new GameObject(joint.Name); val2.transform.SetParent((Transform)((joint.Parent < 0) ? ((object)val.transform) : ((object)creatureRig.joints[joint.Parent])), false); val2.transform.localPosition = V(joint.Position - ((joint.Parent < 0) ? Vector3.Zero : Model.Joints[joint.Parent].Position)); creatureRig.joints[i] = val2.transform; } Mesh val3 = new Mesh { name = "Eavesdropper sinew crawler — original skinned mesh" }; Vector3[] array = (Vector3[])(object)new Vector3[Model.Vertices.Count]; BoneWeight[] array2 = (BoneWeight[])(object)new BoneWeight[array.Length]; for (int j = 0; j < array.Length; j++) { Vertex vertex = Model.Vertices[j]; array[j] = V(vertex.Position); int num = j; BoneWeight val4 = default(BoneWeight); ((BoneWeight)(ref val4)).boneIndex0 = vertex.Joint; ((BoneWeight)(ref val4)).weight0 = 1f; array2[num] = val4; } Matrix4x4[] array3 = (Matrix4x4[])(object)new Matrix4x4[creatureRig.joints.Length]; for (int k = 0; k < array3.Length; k++) { array3[k] = Matrix4x4.Translate(-V(Model.Joints[k].Position)); } val3.vertices = array; val3.boneWeights = array2; val3.bindposes = array3; val3.subMeshCount = 3; for (int l = 0; l < 3; l++) { val3.SetTriangles(Model.Triangles[l], l); } val3.RecalculateNormals(); val3.RecalculateBounds(); SkinnedMeshRenderer val5 = val.AddComponent<SkinnedMeshRenderer>(); val5.sharedMesh = val3; val5.bones = creatureRig.joints; val5.rootBone = creatureRig.joints[0]; val5.updateWhenOffscreen = true; ((Renderer)val5).localBounds = new Bounds(Vector3.up, new Vector3(7f, 6f, 7f)); Shader val6 = Shader.Find("HDRP/Lit") ?? Shader.Find("Standard"); if ((Object)(object)val6 == (Object)null) { throw new InvalidOperationException("HDRP/Lit shader unavailable; supply the documented art bundle."); } Color[] array4 = (Color[])(object)new Color[3] { new Color(0.095f, 0.105f, 0.11f), new Color(0.012f, 0.004f, 0.004f), new Color(0.39f, 0.34f, 0.25f) }; Material[] array5 = (Material[])(object)new Material[3]; for (int m = 0; m < 3; m++) { Material val7 = new Material(val6); ((Object)val7).name = (new string[3] { "Charred sinew", "Facial cavity", "Worn claws" })[m]; Material val8 = val7; val8.SetColor("_BaseColor", array4[m]); if (val8.HasProperty("_Color")) { val8.SetColor("_Color", array4[m]); } if (val8.HasProperty("_Smoothness")) { val8.SetFloat("_Smoothness", (m == 0) ? 0.25f : 0.3f); } if (val8.HasProperty("_Metallic")) { val8.SetFloat("_Metallic", 0f); } array5[m] = val8; } ((Renderer)val5).sharedMaterials = array5; if (!checkedAsset) { checkedAsset = true; advanced = AdvancedVisual.Load(); } if (advanced != null) { val5.sharedMesh = advanced.Mesh; ((Renderer)val5).sharedMaterials = advanced.Materials; val5.quality = (SkinQuality)4; Object.Destroy((Object)(object)val3); Material[] array6 = array5; for (int n = 0; n < array6.Length; n++) { Object.Destroy((Object)(object)array6[n]); } } new GameObject("FacialSlit").transform.SetParent(val.transform, false); creatureRig.Apply("Dormant", 0f, instant: true); return val; } internal void Apply(string clip, float time, bool instant = false, float lookYaw = 0f, float agitation = 0f, float pulse = 0f) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) Model.Pose((clip == "DoorBash") ? "DoorWarn" : clip, time, positions, rotations, agitation); if (advanced != null) { advanced.Sample(clip, time, positions, rotations); } if (!instant && (Object)(object)StartOfRound.Instance != (Object)null) { string[] array = new string[2] { "L", "R" }; RaycastHit val5 = default(RaycastHit); foreach (string text in array) { Vector3 val = ((Component)this).transform.TransformPoint(V(Model.JointPosition("Hand" + text, positions, rotations))); Vector3 val2 = ((Component)this).transform.position + Vector3.up; Vector3 val3 = val + ((Component)this).transform.forward * 0.55f; val3.y = Mathf.Max(val3.y, ((Component)this).transform.position.y + 0.25f); Vector3 val4 = val3 - val2; if (((Vector3)(ref val4)).sqrMagnitude > 0.01f && Physics.SphereCast(val2, 0.18f, ((Vector3)(ref val4)).normalized, ref val5, ((Vector3)(ref val4)).magnitude, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1) && ((RaycastHit)(ref val5)).normal.y < 0.6f) { Vector3 val6 = ((Component)this).transform.InverseTransformPoint(val2 + ((Vector3)(ref val4)).normalized * Mathf.Max(0.05f, ((RaycastHit)(ref val5)).distance - 0.65f)); Model.RefitHand(text, new Vector3(val6.x, val6.y, val6.z), positions, rotations); } } } float num = (instant ? 1f : (1f - Mathf.Exp((float)(-((clip == "Dormant") ? 3 : 14)) * Time.deltaTime))); Quaternion val7 = default(Quaternion); for (int j = 0; j < joints.Length; j++) { joints[j].localPosition = Vector3.Lerp(joints[j].localPosition, V(positions[j]), num); Quaternion quaternion = rotations[j]; ((Quaternion)(ref val7))..ctor(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W); if (Model.Joints[j].Name == "Chest") { val7 = Quaternion.AngleAxis(pulse * 6f, Vector3.right) * val7; } if (advanced != null && Model.Joints[j].Name == "Chest") { val7 = Quaternion.AngleAxis(agitation * (2f + Mathf.Sin(time * 9f)), Vector3.right) * val7; } if (Model.Joints[j].Name == "Head") { val7 = Quaternion.AngleAxis(lookYaw, Vector3.up) * val7; } joints[j].localRotation = Quaternion.Slerp(joints[j].localRotation, val7, num); } } private static Vector3 V(Vector3 p) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(p.X, p.Y, p.Z); } } public sealed class EavesdropperAI : EnemyAI, IWorld { private sealed class EchoObject { public Transform Transform; public PlayerControllerB? Player; public GrabbableObject? Item; public Point First; public float Exposure; public bool Covered; } private DoorLock? doorApproach; private bool suppressDoorNoise; private Vector3 afterDoorGoal; private float doorDeadline; private float doorStarted; private bool doorOpened; private float nextAlternative; internal static readonly HashSet<EavesdropperAI> Live = new HashSet<EavesdropperAI>(); internal Brain Brain; internal Mode DisplayState; internal ulong DisplayTarget = ulong.MaxValue; internal float DisplayHunt; internal float DisplayWarning; internal bool DisplayRecovering; internal bool DisplayCrawling; internal bool DisplayDoorLunge; internal bool DisplayDoorBash; internal float DisplayDoorPhase; private float nextBestiaryRepair; internal float DisplayPhase; internal float DisplayAgitation; internal float MotionPhase; internal float DisplaySpeed; internal float EchoHeadYaw; internal float PulseFlashUntil; internal string NavigationStatus = "Waiting"; internal float HeardLevel; internal bool HeardVoice; internal readonly Dictionary<ulong, (float Level, bool Audible)> VoiceReadings = new Dictionary<ulong, (float, bool)>(); private DoorLock[] doors = Array.Empty<DoorLock>(); private float nextDoors; internal uint SnapshotSequence; internal uint LastSnapshot; internal uint LastDamage; internal Vector3 RemotePosition; internal Quaternion RemoteRotation; internal bool ReceivedSnapshot; internal bool HasBeenAwake; private float nextClientPath; private Vector3 clientCorner; private bool clientDetour; public Transform visualRoot; public Transform facialSlit; public AudioClip rustle; public AudioClip fixation; public AudioClip inhale; public AudioClip echoClick; public AudioClip echoPulse; internal uint HitSequence; public Animator? presentationAnimator; internal bool AnimatorHasAgitation; public CapsuleCollider bodyCollider; private float nextBehaviorLog; private Mode loggedMode; private float loggedAgitation = -1f; private float nextSnapshot; private float pathStarted; private float stuckSince; private Vector3 progressPosition; private bool started; private bool moving; private bool movementBlocked; private readonly NavMeshPath navPath = new NavMeshPath(); private readonly Collider[] attackColliders = (Collider[])(object)new Collider[32]; private readonly SoundEventGate soundEvents = new SoundEventGate(); private readonly RaycastHit[] hearingHits = (RaycastHit[])(object)new RaycastHit[16]; private readonly List<EchoObject> echoObjects = new List<EchoObject>(); private readonly StationaryEvidence stationary = new StationaryEvidence(); private bool finishingEcho; private readonly RaycastHit[] movementHits = (RaycastHit[])(object)new RaycastHit[24]; private readonly FailedRoutes failedRoutes = new FailedRoutes(); private readonly NavMeshPath legPath = new NavMeshPath(); private readonly List<Point> perceivedThreats = new List<Point>(); private readonly List<Point> routePoints = new List<Point>(); private readonly Dictionary<ulong, (Point Position, float Time)> soundMemory = new Dictionary<ulong, (Point, float)>(); private Vector3 travelGoal; private Vector3[] plannedCorners = Array.Empty<Vector3>(); private Vector3[] travelCorners = Array.Empty<Vector3>(); private int travelCorner; private float requestedSpeed; private float nextRepath; private float blockedFor; private float foldedUntil; private float nextClearance; private float nextDetour; private float nextRecovery; private float routeDeadline; private int recoveries; private Vector3 Ear => ((Component)this).transform.position + Vector3.up * 1.5f; Point IWorld.Position => P(((Component)this).transform.position); private int RoomMask => StartOfRound.Instance.collidersAndRoomMaskAndDefault; bool IWorld.Arrived { get { if ((Object)(object)doorApproach == (Object)null && !DisplayDoorBash && moving && travelCorner >= travelCorners.Length - 1 && !base.agent.pathPending) { return base.agent.remainingDistance <= 0.65f; } return false; } } bool IWorld.PathFailed { get { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)doorApproach != (Object)null || DisplayDoorBash) { return false; } if (!((Behaviour)base.agent).enabled || !base.agent.isOnNavMesh || movementBlocked) { return true; } if (Vector3.Distance(progressPosition, ((Component)this).transform.position) > 0.2f) { stuckSince = Time.time; progressPosition = ((Component)this).transform.position; } if (moving && ((!base.agent.pathPending && (int)base.agent.pathStatus != 0) || Time.time - stuckSince > 1.2f || Time.time > routeDeadline)) { if (Time.time <= routeDeadline && RecoverRoute()) { return false; } FailRoute("No travel progress after bounded recovery"); return true; } return false; } } private bool TryAlternateRoute(Vector3 desired, out Vector3 endpoint) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) endpoint = default(Vector3); if (Time.time < nextAlternative || base.allAINodes == null) { return false; } nextAlternative = Time.time + 1.5f; List<Vector3> list = new List<Vector3>(); GameObject[] allAINodes = base.allAINodes; foreach (GameObject val in allAINodes) { if ((Object)(object)val != (Object)null) { list.Add(val.transform.position); } } Vector3 start = ((Component)this).transform.position; list.Sort((Vector3 a, Vector3 b) => (Vector3.Distance(start, a) + Vector3.Distance(a, desired)).CompareTo(Vector3.Distance(start, b) + Vector3.Distance(b, desired))); float num = float.PositiveInfinity; Vector3[] array = null; for (int num2 = 0; num2 < Math.Min(12, list.Count); num2++) { Vector3 val2 = list[num2]; if (Vector3.Distance(start, val2) < 2f || !TryPathFrom(start, val2, navPath, out var endpoint2)) { continue; } Vector3[] collection = plannedCorners; if (TryPathFrom(endpoint2, desired, legPath, out var endpoint3)) { List<Vector3> list2 = new List<Vector3>(collection); for (int num3 = 1; num3 < plannedCorners.Length; num3++) { list2.Add(plannedCorners[num3]); } float num4 = 0f; for (int num5 = 1; num5 < list2.Count; num5++) { num4 += Vector3.Distance(list2[num5 - 1], list2[num5]); } if (num4 < num) { num = num4; array = list2.ToArray(); endpoint = endpoint3; } } } if (array == null) { return false; } plannedCorners = array; NavigationStatus = "Following reachable route via adjoining rooms"; return true; } private bool TryApproachDoor(Vector3 desired, float speed) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) NavMeshHit val = default(NavMeshHit); if (!NavMesh.SamplePosition(desired, ref val, 3.5f, base.agent.areaMask)) { return false; } NavMeshPath val2 = new NavMeshPath(); if (!base.agent.CalculatePath(((NavMeshHit)(ref val)).position, val2) || val2.corners.Length == 0) { return false; } Vector3 val3 = val2.corners[val2.corners.Length - 1]; DoorLock val4 = null; Vector3[] array = null; float num = float.PositiveInfinity; int num2 = 0; DoorLock[] array2 = doors; foreach (DoorLock val5 in array2) { if ((Object)(object)val5 == (Object)null || val5.isLocked) { continue; } NavMeshObstacle component = ((Component)val5).GetComponent<NavMeshObstacle>(); if ((Object)(object)component == (Object)null || !((Behaviour)component).enabled) { continue; } bool flag = Vector3.Distance(val3, ((Component)val5).transform.position) < 3.5f; for (int j = 1; j < val2.corners.Length; j++) { if (flag) { break; } flag = NavigationPolicy.SegmentDistance(P(((Component)val5).transform.position), P(val2.corners[j - 1]), P(val2.corners[j])) < 1.5f; } if (!flag || num2++ >= 8 || (Object)(object)((Component)val5).GetComponent<AnimatedObjectTrigger>() == (Object)null) { continue; } for (int k = 0; k < 8; k++) { float num3 = (float)k * MathF.PI / 4f; Vector3 desired2 = ((Component)val5).transform.position + new Vector3(Mathf.Cos(num3), 0f, Mathf.Sin(num3)) * 1.6f; if (!TryPath(desired2, navPath, out var endpoint)) { continue; } Vector3 step = ((Component)val5).transform.position - endpoint; step.y = 0f; if (!BodyHit(endpoint, step, out var nearest, compact: true) || (!((Object)(object)((RaycastHit)(ref nearest)).collider == (Object)null) && !((Object)(object)((Component)((RaycastHit)(ref nearest)).collider).GetComponentInParent<DoorLock>() != (Object)(object)val5))) { float num4 = 0f; for (int l = 1; l < plannedCorners.Length; l++) { num4 += Vector3.Distance(plannedCorners[l - 1], plannedCorners[l]); } if (num4 < num) { num = num4; val4 = val5; array = plannedCorners; } } } } if ((Object)(object)val4 == (Object)null || array == null) { return false; } doorApproach = val4; afterDoorGoal = desired; requestedSpeed = speed; travelCorners = array; travelCorner = 1; travelGoal = array[^1]; base.agent.isStopped = false; base.agent.speed = Mathf.Min(speed, 4f); moving = SetLeg(); movementBlocked = false; blockedFor = 0f; doorDeadline = Time.time + Mathf.Max(10f, num / Mathf.Max(1f, base.agent.speed) * 2f + 5f); doorStarted = -1f; doorOpened = false; if (!moving) { doorApproach = null; return false; } NavigationStatus = "Approaching closed ordinary door on route to sound"; return true; } private bool UpdateDoorInteraction() { //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)doorApproach == (Object)null) { return false; } Mode state = Brain.State; bool flag = ((state == Mode.Dormant || state - 6 <= Mode.Fixated) ? true : false); if (flag || base.stunNormalizedTimer > 0f || base.stunnedIndefinitely > 0 || Time.time > doorDeadline) { doorApproach = null; DisplayDoorBash = false; FailRoute("Door interaction interrupted or timed out"); return false; } DoorLock val = doorApproach; if (val.isLocked) { FailRoute("Door became locked"); return false; } if (doorStarted < 0f) { if (Vector3.Distance(((Component)this).transform.position, ((Component)val).transform.position) > 2.3f) { return false; } Vector3 val2 = ((Component)val).transform.position - ((Component)this).transform.position; val2.y = 0f; if (BodyHit(((Component)this).transform.position, val2, out var nearest, compact: true) && ((Object)(object)((RaycastHit)(ref nearest)).collider == (Object)null || (Object)(object)((Component)((RaycastHit)(ref nearest)).collider).GetComponentInParent<DoorLock>() != (Object)(object)val)) { return false; } doorStarted = Time.time; base.agent.isStopped = true; base.agent.nextPosition = ((Component)this).transform.position; if (((Vector3)(ref val2)).sqrMagnitude > 0.01f) { ((Component)this).transform.rotation = Quaternion.LookRotation(val2); } } DisplayDoorBash = true; DisplayDoorPhase = Time.time - doorStarted; DisplaySpeed = 0f; DisplayCrawling = true; base.agent.nextPosition = ((Component)this).transform.position; stuckSince = Time.time; if (!doorOpened && DisplayDoorPhase >= 0.5f) { doorOpened = true; NavMeshObstacle component = ((Component)val).GetComponent<NavMeshObstacle>(); if ((Object)(object)component != (Object)null && ((Behaviour)component).enabled) { suppressDoorNoise = true; try { ((Component)val).GetComponent<AnimatedObjectTrigger>().TriggerAnimationNonPlayer(true, true, false); } finally { suppressDoorNoise = false; } val.OpenDoorAsEnemy(true); val.OpenDoorAsEnemyClientRpc(); } } if (DisplayDoorPhase >= 1.2f) { Vector3 v = afterDoorGoal; float speed = requestedSpeed; doorApproach = null; DisplayDoorBash = false; moving = false; if (!((IWorld)this).Move(P(v), speed)) { movementBlocked = true; } } return true; } public override void Awake() { } public override void Start() { //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: 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_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 if (!((NetworkBehaviour)this).IsSpawned || (Object)(object)RoundManager.Instance == (Object)null) { return; } ((EnemyAI)this).Awake(); ((EnemyAI)this).Start(); base.movingTowardsTargetPlayer = false; base.moveTowardsDestination = false; started = true; Live.Add(this); if ((Object)(object)presentationAnimator != (Object)null) { AnimatorControllerParameter[] parameters = presentationAnimator.parameters; foreach (AnimatorControllerParameter val in parameters) { if (val.name == "Agitation" && (int)val.type == 1) { AnimatorHasAgitation = true; } } } Brain = new Brain(Plugin.Settings, this); ((Behaviour)base.agent).enabled = ((NetworkBehaviour)this).IsServer; base.agent.updatePosition = false; base.agent.updateRotation = false; base.agent.radius = 0.55f; base.agent.autoBraking = true; base.agent.autoRepath = true; base.agent.stoppingDistance = 0.08f; base.agent.obstacleAvoidanceType = (ObstacleAvoidanceType)4; base.ventAnimationFinished = true; base.postStunInvincibilityTimer = -1f; NavMeshHit val2 = default(NavMeshHit); if (((NetworkBehaviour)this).IsServer && !base.agent.isOnNavMesh && NavMesh.SamplePosition(((Component)this).transform.position, ref val2, 3f, base.agent.areaMask)) { base.agent.Warp(((NavMeshHit)(ref val2)).position); } if (((NetworkBehaviour)this).IsServer && !base.agent.isOnNavMesh) { Plugin.Instance.Log("Eavesdropper spawn had no nearby NavMesh; despawning safely."); ((NetworkBehaviour)this).NetworkObject.Despawn(true); return; } RepairBestiary(); RemotePosition = ((Component)this).transform.position; RemoteRotation = ((Component)this).transform.rotation; progressPosition = ((Component)this).transform.position; stuckSince = Time.time; if (((NetworkBehaviour)this).IsServer) { ((IWorld)this).Stop(); } } public override void Update() { //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_0462: Unknown result type (might be due to invalid IL or missing references) //IL_0468: Unknown result type (might be due to invalid IL or missing references) //IL_0483: Unknown result type (might be due to invalid IL or missing references) //IL_0553: Unknown result type (might be due to invalid IL or missing references) //IL_0569: Unknown result type (might be due to invalid IL or missing references) //IL_03fc: Unknown result type (might be due to invalid IL or missing references) //IL_0402: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_042a: Unknown result type (might be due to invalid IL or missing references) //IL_042f: Unknown result type (might be due to invalid IL or missing references) //IL_0436: Unknown result type (might be due to invalid IL or missing references) //IL_043b: Unknown result type (might be due to invalid IL or missing references) //IL_03b0: Unknown result type (might be due to invalid IL or missing references) //IL_0450: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_03e9: Unknown result type (might be due to invalid IL or missing references) if (!started || !((NetworkBehaviour)this).IsSpawned) { return; } if (Time.time >= nextBestiaryRepair) { nextBestiaryRepair = Time.time + 2f; RepairBestiary(); } if (((NetworkBehaviour)this).IsServer) { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null && RoundLifetime.ShouldDespawn(((NetworkBehaviour)this).IsServer, ((NetworkBehaviour)this).IsSpawned, instance.shipIsLeaving, instance.inShipPhase, instance.allPlayersDead)) { ((IWorld)this).Stop(); SessionWire.Forget(((NetworkBehaviour)this).NetworkObjectId); ((NetworkBehaviour)this).NetworkObject.Despawn(true); return; } if (Time.time >= nextDoors) { doors = Object.FindObjectsOfType<DoorLock>(); nextDoors = Time.time + 5f; } UpdateClearance(); if (!UpdateDoorInteraction()) { ApplyAgentMovement(); } if (base.stunnedIndefinitely <= 0) { base.stunNormalizedTimer -= Time.deltaTime / Math.Max(0.01f, base.enemyType.stunTimeMultiplier); } if (base.stunNormalizedTimer < 0f) { base.postStunInvincibilityTimer -= Time.deltaTime * 5f; } if (base.stunnedIndefinitely > 0 && !SessionWire.Valid(base.stunnedByPlayer)) { base.stunnedIndefinitely = 0; } Brain.Tick(Time.deltaTime, base.stunNormalizedTimer > 0f || base.stunnedIndefinitely > 0); CopyDisplay(); if (Time.time >= nextBehaviorLog) { nextBehaviorLog = Time.time + 1f; if (Plugin.Settings.DebugBehaviorLogging && loggedMode != Brain.State) { Plugin.Instance.Log($"Enemy {((NetworkBehaviour)this).NetworkObjectId}: {loggedMode} -> {Brain.State}, confidence={Brain.Confidence:F2}, persistence={Brain.HuntRemaining:F1}s"); } if (Plugin.Settings.DebugAgitationLogging && Mathf.Abs(loggedAgitation - Brain.Agitation) >= 1f) { Plugin.Instance.Log($"Enemy {((NetworkBehaviour)this).NetworkObjectId}: agitation={Brain.Agitation:F1}, tier={Brain.Tier}, dormant inactivity={Brain.RestSeconds:F1}s"); } loggedMode = Brain.State; loggedAgitation = Brain.Agitation; } if (Time.time >= nextSnapshot) { nextSnapshot = Time.time + 0.1f; SessionWire.Snapshot(this); } } else if (ReceivedSnapshot) { Vector3 val = Vector3.Lerp(((Component)this).transform.position, RemotePosition, 1f - Mathf.Exp(-18f * Time.deltaTime)); if (!BodyHit(((Component)this).transform.position, val - ((Component)this).transform.position, out var nearest)) { ((Component)this).transform.position = val; } else { if (Time.time >= nextClientPath) { nextClientPath = Time.time + 0.2f; clientDetour = NavMesh.CalculatePath(((Component)this).transform.position, RemotePosition, -1, navPath) && (int)navPath.status == 0 && navPath.corners.Length > 1; if (clientDetour) { clientCorner = navPath.corners[1]; } } if (clientDetour) { Vector3 val2 = Vector3.MoveTowards(((Component)this).transform.position, clientCorner, Mathf.Max(1f, DisplaySpeed) * Time.deltaTime); if (!BodyHit(((Component)this).transform.position, val2 - ((Component)this).transform.position, out nearest)) { ((Component)this).transform.position = val2; } } } ((Component)this).transform.rotation = Quaternion.Slerp(((Component)this).transform.rotation, RemoteRotation, 1f - Mathf.Exp(-18f * Time.deltaTime)); DisplayHunt = Mathf.Max(0f, DisplayHunt - Time.deltaTime); DisplayWarning = Mathf.Max(0f, DisplayWarning - Time.deltaTime); DisplayPhase += Time.deltaTime; if (DisplayDoorBash) { DisplayDoorPhase += Time.deltaTime; } if (DisplaySpeed > 0.08f) { MotionPhase += Time.deltaTime; } } if ((Object)(object)bodyCollider != (Object)null) { bodyCollider.height = (DisplayCrawling ? 1.65f : 2.45f); bodyCollider.radius = 0.55f; bodyCollider.center = Vector3.up * (bodyCollider.height * 0.5f); } EchoHeadYaw = Mathf.MoveTowards(EchoHeadYaw, 0f, Time.deltaTime * 180f); Presentation.Pose(this); } internal void CopyDisplay() { DisplayState = Brain.State; DisplayTarget = Brain.Target; DisplayHunt = Brain.HuntRemaining; DisplayWarning = Brain.WarningRemaining; DisplayRecovering = Brain.Recovering; DisplayDoorLunge = Brain.DoorLunge; DisplayPhase = Brain.StateSeconds; DisplayAgitation = Brain.Agitation; base.currentBehaviourStateIndex = (int)DisplayState; } private void RepairBestiary() { Terminal val = Object.FindObjectOfType<Terminal>(); if (!((Object)(object)val == (Object)null) && !((Object)(object)Plugin.Bestiary == (Object)null) && val.enemyFiles.Contains(Plugin.Bestiary)) { int creatureFileID = Plugin.Bestiary.creatureFileID; ScanNodeProperties[] componentsInChildren = ((Component)this).GetComponentsInChildren<ScanNodeProperties>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].creatureScanID = creatureFileID; } } } public override void DoAIInterval() { } public override void OnCollideWithPlayer(Collider other) { } public override void SetEnemyStunned(bool setToStunned, float setToStunTime = 1f, PlayerControllerB? setStunnedByPlayer = null) { if (started && ((NetworkBehaviour)this).IsServer) { ((EnemyAI)this).SetEnemyStunned(setToStunned, setToStunTime, setStunnedByPlayer); } } public override void HitEnemy(int force = 1, PlayerControllerB? playerWhoHit = null, bool playHitSFX = false, int hitID = -1) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (started && ((NetworkBehaviour)this).IsServer && SessionWire.Valid(playerWhoHit) && force >= 1 && !(Vector3.Distance(((Component)this).transform.position, ((Component)playerWhoHit).transform.position) > 4f) && !Blocked(Ear, ((Component)playerWhoHit).transform.position + Vector3.up)) { ((EnemyAI)this).SetEnemyStunned(true, 0.6f, playerWhoHit); } } public override void DetectNoise(Vector3 noisePosition, float noiseLoudness, int timesPlayedInSameSpot = 0, int noiseID = 0) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) if (started && ((NetworkBehaviour)this).IsServer && !GameSoundHooks.InSourceCallback && !suppressDoorNoise && noiseID != 1974301 && noiseID != 75 && noiseID != 6 && Finite(noisePosition) && float.IsFinite(noiseLoudness) && !(noiseLoudness < Plugin.Settings.NoiseThreshold) && soundEvents.Accept(noiseID, P(noisePosition), Time.time, 0.15f)) { HeardSound(SoundKind.Ordinary, (ulong)noiseID, noisePosition, Plugin.Settings.NoiseRange, noiseLoudness, 0.15f, ulong.MaxValue); } } internal void HeardSound(SoundKind kind, ulong source, Vector3 position, float range, float loudness, float duration, ulong player = ulong.MaxValue) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (!started || !((NetworkBehaviour)this).IsServer) { return; } float num = Audibility(position + Vector3.up * 0.5f, range, loudness); if (!(num <= 0f)) { if (!Brain.SensorySuppressed) { RememberSound(position, source); } Brain.Sound(kind, source, P(position), num, duration, player); } } internal void Repellent(ulong source, Vector3 position, float loudness, bool initial, float duration) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) if (!started || !((NetworkBehaviour)this).IsServer) { return; } float num = Audibility(position + Vector3.up * 0.5f, Plugin.Settings.ContinuousNoiseRange, loudness); if (num <= 0f) { return; } if (initial) { RememberSound(position, source); Brain.Scare(P(position)); } if (duration > 0f) { if (Brain.SensorySuppressed || Brain.State == Mode.Retreating) { Brain.Irritation(num, duration); } else { Brain.Sound(SoundKind.Ordinary, source, P(position), num, duration, ulong.MaxValue); } } } internal void Voice(PlayerControllerB player, ushort amplitude, float credit) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_00df: Unknown result type (might be due to invalid IL or missing references) if (!started || !((NetworkBehaviour)this).IsServer) { return; } HeardLevel = VoiceActivity.Level(amplitude, Plugin.Settings.VoiceSensitivity); HeardVoice = false; if (HeardLevel < Plugin.Settings.VoiceThreshold) { VoiceReadings[player.actualClientId] = (HeardLevel, false); return; } Vector3 position = ((Component)player).transform.position; float num = Audibility(position + Vector3.up * 1.5f, Plugin.Settings.VoiceRange, 1f); HeardVoice = num > 0f && !Brain.SensorySuppressed; VoiceReadings[player.actualClientId] = (HeardLevel, HeardVoice); if (HeardVoice) { RememberSound(position, player.actualClientId); } Brain.Sound(SoundKind.Voice, player.actualClientId, P(position), num, credit, player.actualClientId); } private float Audibility(Vector3 point, float range, float level) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) range = Mathf.Min(range, Plugin.Settings.NoiseRange); float num = Vector3.Distance(Ear, point); if (range <= 0f || num > range || level <= 0f) { return 0f; } Vector3 ear = Ear; Vector3 val = point - Ear; int num2 = Physics.RaycastNonAlloc(ear, ((Vector3)(ref val)).normalized, hearingHits, num, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1); HashSet<int> hashSet = new HashSet<int>(); for (int i = 0; i < num2; i++) { if ((Object)(object)((RaycastHit)(ref hearingHits[i])).collider != (Object)null) { hashSet.Add(((Object)((RaycastHit)(ref hearingHits[i])).collider).GetInstanceID()); } } float num3 = Mathf.Pow(Plugin.Settings.ObstructionMultiplier, (float)Mathf.Min(4, hashSet.Count)); float num4 = range * num3; if (num > num4) { return 0f; } return Mathf.Clamp01(level) * num3 * Mathf.Max(0.05f, 1f - num / Mathf.Max(0.1f, num4)); } internal static bool Blocked(Vector3 a, Vector3 b) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)StartOfRound.Instance == (Object)null)) { return Physics.Linecast(a, b, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1); } return true; } internal static bool Finite(Vector3 p) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (float.IsFinite(p.x) && float.IsFinite(p.y)) { return float.IsFinite(p.z); } return false; } internal static Point P(Vector3 v) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) return new Point(v.x, v.y, v.z); } internal static Vector3 V(Point p) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(p.X, p.Y, p.Z); } bool IWorld.ValidPlayer(ulong id) { return (Object)(object)SessionWire.FindPlayer(id) != (Object)null; } private DoorLock? NearbyDoor() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) DoorLock[] array = doors; foreach (DoorLock val in array) { if (!((Object)(object)val == (Object)null) && !val.isLocked && !(Vector3.Distance(((Component)this).transform.position, ((Component)val).transform.position) > 2.1f)) { NavMeshObstacle component = ((Component)val).GetComponent<NavMeshObstacle>(); if ((Object)(object)component != (Object)null && !((Behaviour)component).enabled) { return val; } } } return null; } void IWorld.Face(Point aim) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) Vector3 val = V(aim) - ((Component)this).transform.position; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude > 0.01f) { ((Component)this).transform.rotation = Quaternion.LookRotation(val); } } bool IWorld.AttackOpportunity(Point aim) { return (Object)(object)CloseVictim(aim) != (Object)null; } private PlayerControllerB? CloseVictim(Point aim) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //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) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) int num = Physics.OverlapSphereNonAlloc(Ear, Plugin.Settings.AttackRange, attackColliders, StartOfRound.Instance.playersMask, (QueryTriggerInteraction)2); PlayerControllerB result = null; float num2 = float.MaxValue; Vector3 val = V(aim) - ((Component)this).transform.position; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = ((Component)this).transform.forward; } for (int i = 0; i < num; i++) { PlayerControllerB componentInParent = ((Component)attackColliders[i]).GetComponentInParent<PlayerControllerB>(); if (SessionWire.Valid(componentInParent)) { Vector3 val2 = ((Component)componentInParent).transform.position + Vector3.up; Vector3 val3 = val2 - Ear; Vector3 val4 = val3; val4.y = 0f; if (!(Vector3.Angle(val, val4) > 60f) && !(((Vector3)(ref val3)).magnitude > Plugin.Settings.AttackRange) && !Blocked(Ear, val2) && ((Vector3)(ref val3)).sqrMagnitude < num2) { result = componentInParent; num2 = ((Vector3)(ref val3)).sqrMagnitude; } } } return result; } bool IWorld.Strike(Point aim, int damage) { if (!((NetworkBehaviour)this).IsServer || Brain.State != Mode.Attacking || base.stunNormalizedTimer > 0f || base.stunnedIndefinitely > 0) { return false; } PlayerControllerB val = CloseVictim(aim); if ((Object)(object)val != (Object)null) { return SessionWire.Damage(this, val, damage); } return false; } void IWorld.Search(Point center, float speed) { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (base.allAINodes != null && base.allAINodes.Length != 0) { int num = Random.Range(0, base.allAINodes.Length); for (int i = 0; i < Math.Min(12, base.allAINodes.Length); i++) { GameObject val = base.allAINodes[(num + i) % base.allAINodes.Length]; if (!((Object)(object)val == (Object)null)) { Vector3 position = val.transform.position; if (!(Vector3.Distance(position, V(center)) > 18f) && !(Vector3.Distance(position, ((Component)this).transform.position) < 2f) && ((IWorld)this).Move(P(position), speed)) { return; } } } } Vector2 val2 = Random.insideUnitCircle * 5f; ((IWorld)this).Move(new Point(center.X + val2.x, center.Y, center.Z + val2.y), speed); } void IWorld.Signal(Cue cue) { if (cue == Cue.EchoWarning) { PrepareEcho(); } CopyDisplay(); SessionWire.Signal(this, cue); } public override void OnDestroy() { Live.Remove(this); if (started) { SessionWire.Forget(((NetworkBehaviour)this).NetworkObjectId); } if (started && (Object)(object)RoundManager.Instance != (Object)null) { ((EnemyAI)this).OnDestroy(); } } private void PrepareEcho() { echoObjects.Clear(); NavigationStatus = "Echo preparation: ears spread, throat rattle"; } void IWorld.CancelEcho() { echoObjects.Clear(); if (!finishingEcho) { stationary.Clear(); } finishingEcho = false; } bool IWorld.EchoReady() { return SessionWire.EchoReady(this); } void IWorld.EchoFirst() { //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) echoObjects.Clear(); PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (SessionWire.Valid(val) && SessionWire.EchoWarned(this, val.actualClientId)) { echoObjects.Add(new EchoObject { Transform = ((Component)val).transform, Player = val }); } } GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>(); foreach (GrabbableObject val2 in array) { if ((Object)(object)val2 != (Object)null && val2.isInFactory && !val2.isHeld && !val2.isHeldByEnemy && Vector3.Distance(((Component)this).transform.position, ((Component)val2).transform.position) < Plugin.Settings.EchoRange + 2f) { echoObjects.Add(new EchoObject { Transform = ((Component)val2).transform, Item = val2 }); } } foreach (EchoObject echoObject in echoObjects) { echoObject.First = P(echoObject.Transform.position); echoObject.Exposure = Exposure(echoObject.Transform.position, (Object)(object)echoObject.Item != (Object)null); echoObject.Covered = Clutter(echoObject.Transform.position); } NavigationStatus = "First chirp sampled; waiting for second"; } private float Exposure(Vector3 point, bool item) { //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: 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_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: 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) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: 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_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_0216: 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_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) float num = Plugin.Settings.EchoRange; DoorLock[] array = doors; foreach (DoorLock val in array) { if ((Object)(object)val == (Object)null || val.isLocked) { continue; } NavMeshObstacle component = ((Component)val).GetComponent<NavMeshObstacle>(); if (!((Object)(object)component == (Object)null) && !((Behaviour)component).enabled) { Vector3 val2 = point - ((Component)this).transform.position; float num2 = Vector3.Dot(((Component)val).transform.position - ((Component)this).transform.position, val2) / Mathf.Max(0.001f, ((Vector3)(ref val2)).sqrMagnitude); if (num2 > 0f && num2 < 1f && NavigationPolicy.SegmentDistance(P(((Component)val).transform.position), P(((Component)this).transform.position), P(point)) < 1.1f) { num *= Plugin.Settings.EchoDoorMultiplier; break; } } } if (Vector3.Distance(Ear, point + Vector3.up * (float)((!item) ? 1 : 0)) > num) { return 0f; } if (item) { return (!Blocked(Ear, point)) ? 1 : 0; } int num3 = 0; Vector3[] array2 = (Vector3[])(object)new Vector3[5] { point + Vector3.up * 1.55f, point + Vector3.up, point + Vector3.up * 0.45f, point + Vector3.up + Vector3.right * 0.22f, point + Vector3.up - Vector3.right * 0.22f }; foreach (Vector3 val3 in array2) { bool flag = !Blocked(Ear, val3); if (flag) { num3++; } if (Plugin.Settings.DebugEchoVisualization) { Debug.DrawLine(Ear, val3, flag ? Color.green : Color.red, 1f); } } return (float)num3 / 5f; } private bool Clutter(Vector3 point) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) int num = 0; Vector3 val = point + Vector3.up * 0.9f; Vector3 val2 = default(Vector3); for (int i = 0; i < 8; i++) { float num2 = (float)i * MathF.PI / 4f; ((Vector3)(ref val2))..ctor(Mathf.Cos(num2), 0f, Mathf.Sin(num2)); if (Physics.Raycast(val, val2, 1.2f, RoomMask, (QueryTriggerInteraction)1)) { num++; } } return num >= 3; } EchoResult IWorld.EchoTarget() { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (mig