using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using HarmonyLib; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem.Collections.Generic; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("BigWalk.VoiceSettings")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Best-in-class Big Walk voice controls: adjustable proximity range, 2D audio, named speaker HUD, quick actions, and polished in-game feedback.")] [assembly: AssemblyFileVersion("1.4.0.0")] [assembly: AssemblyInformationalVersion("1.4.0+48d31be321cabd0bfd7797066d6a8f3764a5f7e9")] [assembly: AssemblyProduct("BigWalk.VoiceSettings")] [assembly: AssemblyTitle("BigWalk.VoiceSettings")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.4.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 BigWalk.VoiceSettings { internal static class NativeSettingsIntegration { private sealed class AudioScrollState { private const float EdgePadding = 18f; private readonly SettingsMenu _menu; private readonly RectTransform _content; private readonly RectTransform _viewport; private readonly ScrollRect _scrollRect; private readonly bool _ownsScrollRect; private bool _wasActive; private bool _reportedTickError; private GameObject _lastSelection; public AudioScrollState(SettingsMenu menu, RectTransform content, RectTransform viewport) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Expected O, but got Unknown //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) _menu = menu; _content = content; _viewport = viewport; ContentSizeFitter val = ((Component)content).GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)content).gameObject.AddComponent(); } val.horizontalFit = (FitMode)0; val.verticalFit = (FitMode)2; if ((Object)(object)((Component)viewport).GetComponent() == (Object)null && (Object)(object)((Component)viewport).GetComponent() == (Object)null) { ((Component)viewport).gameObject.AddComponent(); } Image val2 = ((Component)viewport).GetComponent(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)viewport).gameObject.AddComponent(); } ((Graphic)val2).color = new Color(0f, 0f, 0f, 0f); ((Graphic)val2).raycastTarget = true; _scrollRect = ((Component)viewport).GetComponent(); if ((Object)(object)_scrollRect == (Object)null) { _scrollRect = ((Component)viewport).gameObject.AddComponent(); _ownsScrollRect = true; } _scrollRect.content = content; _scrollRect.viewport = viewport; _scrollRect.horizontal = false; _scrollRect.vertical = true; _scrollRect.movementType = (MovementType)2; _scrollRect.inertia = true; _scrollRect.decelerationRate = 0.135f; _scrollRect.scrollSensitivity = 72f; LayoutRebuilder.ForceRebuildLayoutImmediate(content); Canvas.ForceUpdateCanvases(); _scrollRect.verticalNormalizedPosition = 1f; ManualLogSource trace = Plugin.Trace; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(55, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Audio scrolling enabled: content '"); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(((Object)((Component)content).gameObject).name); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' "); Rect rect = content.rect; ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(((Rect)(ref rect)).height, "0"); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("px, "); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("viewport '"); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(((Object)((Component)viewport).gameObject).name); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' "); rect = viewport.rect; ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(((Rect)(ref rect)).height, "0"); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("px."); } trace.LogInfo(val3); } public void Tick() { //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown try { if ((Object)(object)_menu == (Object)null || (Object)(object)_content == (Object)null || (Object)(object)_viewport == (Object)null) { return; } bool flag = ((Behaviour)_menu).isActiveAndEnabled && (Object)(object)_menu.activeCatagory == (Object)(object)_menu.catagoryAudio; if (_ownsScrollRect) { ((Behaviour)_scrollRect).enabled = flag; } if (!flag) { _wasActive = false; return; } if (!_wasActive) { LayoutRebuilder.ForceRebuildLayoutImmediate(_content); Canvas.ForceUpdateCanvases(); _scrollRect.verticalNormalizedPosition = 1f; _wasActive = true; } KeepSelectionVisible(); } catch (Exception ex) { if (!_reportedTickError) { _reportedTickError = true; ManualLogSource trace = Plugin.Trace; bool flag2 = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(64, 1, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Audio scrolling update failed (further occurrences suppressed): "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } trace.LogWarning(val); } } } private void KeepSelectionVisible() { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_00a2: 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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: 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_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_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) EventSystem current = EventSystem.current; GameObject val = ((current != null) ? current.currentSelectedGameObject : null); if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)_lastSelection) { return; } Transform val2 = val.transform; bool flag = false; while ((Object)(object)val2 != (Object)null) { if ((Object)(object)val2 == (Object)(object)_content) { flag = true; break; } val2 = val2.parent; } if (!flag) { return; } _lastSelection = val; RectTransform component = val.GetComponent(); if ((Object)(object)component == (Object)null) { return; } float num = Mathf.Abs(((Transform)component).lossyScale.y); float num2 = Mathf.Abs(((Transform)_viewport).lossyScale.y); Rect rect = component.rect; float num3 = ((Rect)(ref rect)).height * num * 0.5f; rect = _viewport.rect; float num4 = ((Rect)(ref rect)).height * num2 * 0.5f; float num5 = ((Transform)component).position.y - num3; float num6 = ((Transform)component).position.y + num3; float num7 = ((Transform)_viewport).position.y - num4 + 18f; float num8 = ((Transform)_viewport).position.y + num4 - 18f; Vector2 anchoredPosition = _content.anchoredPosition; if (num5 < num7) { anchoredPosition.y += (num7 - num5) / Mathf.Max(num, 0.001f); } else { if (!(num6 > num8)) { return; } anchoredPosition.y -= (num6 - num8) / Mathf.Max(num, 0.001f); } float preferredHeight = LayoutUtility.GetPreferredHeight(_content); rect = _viewport.rect; float num9 = Mathf.Max(0f, preferredHeight - ((Rect)(ref rect)).height); anchoredPosition.y = Mathf.Clamp(anchoredPosition.y, 0f, num9); _content.anchoredPosition = anchoredPosition; _scrollRect.StopMovement(); } } private const string RootName = "BigWalk.VoiceSettings.Native.Positioning"; private const string PositioningName = "BigWalk.VoiceSettings.Native.Positioning"; private const string RangeName = "BigWalk.VoiceSettings.Native.Range"; private const string IndicatorsName = "BigWalk.VoiceSettings.Native.Indicators"; private const string AdvancedName = "BigWalk.VoiceSettings.Native.Advanced"; private static readonly float[] RangePresets = new float[5] { 1f, 2f, 5f, 10f, 20f }; private static readonly string[] RangeLabels = new string[5] { "VANILLA ×1", "SOCIAL ×2", "WIDE ×5", "FAR ×10", "MAXIMUM ×20" }; private static readonly Dictionary Scrollers = new Dictionary(); public static void Ensure() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown try { foreach (SettingsMenu item in Object.FindObjectsOfType(true)) { Attach(item); } } catch (Exception ex) { ManualLogSource trace = Plugin.Trace; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(40, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not attach native Audio settings: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex); } trace.LogError(val); } } public static void Refresh() { foreach (SettingsMenu item in Object.FindObjectsOfType(true)) { Refresh(item); } } public static void Tick() { foreach (AudioScrollState value in Scrollers.Values) { value.Tick(); } } private static void Attach(SettingsMenu menu) { //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Expected O, but got Unknown SettingsMenu obj = menu; SettingsCatagory val = ((obj != null) ? obj.catagoryAudio : null); if (((val != null) ? val.rows : null) == null || ((Il2CppArrayBase)(object)val.rows).Length == 0) { return; } Transform val2 = FindDescendant(((Component)menu).transform, "BigWalk.VoiceSettings.Native.Positioning"); if ((Object)(object)val2 != (Object)null) { EnsureScroller(menu, val2.parent); Refresh(menu); return; } SettingsRow val3 = FindCycleTemplate(val); if ((Object)(object)val3 == (Object)null) { return; } SettingsRow obj2 = FindSliderTemplate(val); Transform parent = ((Component)val3).transform.parent; int sibling = LastAudioSibling(val) + 1; List list = new List(); SettingsRow val4 = CloneRow(val3, parent, sibling++, "BigWalk.VoiceSettings.Native.Positioning"); ConfigureCycleRow(val4, "VOICE POSITIONING", () => (!Plugin.Instance.TwoDVoice.Value) ? "3D SPATIAL" : "2D EVERYWHERE", delegate { Plugin.Instance.TwoDVoice.Value = !Plugin.Instance.TwoDVoice.Value; ApplyAndRefresh(); }); list.Add(val4); if (obj2 == null) { obj2 = val3; } SettingsRow val5 = CloneRow(obj2, parent, sibling++, "BigWalk.VoiceSettings.Native.Range"); if ((Object)(object)val5.slider != (Object)null) { ConfigureSliderRow(val5, "PROXIMITY RANGE", Plugin.Instance.RangeMultiplier.Value, delegate(float value) { Plugin.Instance.RangeMultiplier.Value = value; ApplyAndRefresh(); }); } else { ConfigureCycleRow(val5, "PROXIMITY RANGE", RangeLabel, delegate(int delta) { int num = ClosestRangeIndex(Plugin.Instance.RangeMultiplier.Value); num = (num + delta + RangePresets.Length) % RangePresets.Length; Plugin.Instance.RangeMultiplier.Value = RangePresets[num]; ApplyAndRefresh(); }); } list.Add(val5); SettingsRow val6 = CloneRow(val3, parent, sibling++, "BigWalk.VoiceSettings.Native.Indicators"); ConfigureCycleRow(val6, "SPEAKER INDICATORS", IndicatorLabel, delegate(int delta) { SetIndicatorIndex((IndicatorIndex() + delta + 3) % 3); Refresh(); }); list.Add(val6); SettingsRow val7 = FindButtonTemplate(menu); SettingsRow val8 = (((Object)(object)val7 != (Object)null) ? CloneRow(val7, parent, sibling, "BigWalk.VoiceSettings.Native.Advanced") : CloneRow(val3, parent, sibling, "BigWalk.VoiceSettings.Native.Advanced")); if ((Object)(object)val8.boringButton != (Object)null) { ConfigureButtonRow(val8, "BETTER PROXIMITY VOICE", "ADVANCED SETTINGS", delegate { Plugin.Instance.Overlay.OpenFromNativeSettings(menu); }); } else { ConfigureCycleRow(val8, "ADVANCED VOICE SETTINGS", () => "OPEN", delegate { Plugin.Instance.Overlay.OpenFromNativeSettings(menu); }); } list.Add(val8); RebuildNavigation(val, list); RectTransform val9 = AsRect(parent); if ((Object)(object)val9 != (Object)null) { LayoutRebuilder.ForceRebuildLayoutImmediate(val9); } EnsureScroller(menu, parent); Refresh(menu); ManualLogSource trace = Plugin.Trace; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val10 = new BepInExInfoLogInterpolatedStringHandler(47, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val10).AppendLiteral("Added native voice controls to "); ((BepInExLogInterpolatedStringHandler)val10).AppendFormatted(menu.isInMainMenu ? "main-menu" : "in-game"); ((BepInExLogInterpolatedStringHandler)val10).AppendLiteral(" Audio settings."); } trace.LogInfo(val10); } private static SettingsRow FindCycleTemplate(SettingsCatagory category) { foreach (SettingsRow item in (Il2CppArrayBase)(object)category.rows) { if ((Object)(object)item != (Object)null && (Object)(object)item.leftButton != (Object)null && (Object)(object)item.rightButton != (Object)null && (Object)(object)item.arrayLabel != (Object)null) { return item; } } return null; } private static SettingsRow FindSliderTemplate(SettingsCatagory category) { foreach (SettingsRow item in (Il2CppArrayBase)(object)category.rows) { if ((Object)(object)item != (Object)null && (Object)(object)item.slider != (Object)null && (Object)(object)item.sliderLabel != (Object)null) { return item; } } return null; } private static SettingsRow FindButtonTemplate(SettingsMenu menu) { SettingsCatagory[] array = (SettingsCatagory[])(object)new SettingsCatagory[4] { menu.catagoryAudio, menu.catagoryGeneral, menu.catagoryControls, menu.catagoryGraphics }; foreach (SettingsCatagory val in array) { if (((val != null) ? val.rows : null) == null) { continue; } foreach (SettingsRow item in (Il2CppArrayBase)(object)val.rows) { if ((Object)(object)item != (Object)null && (Object)(object)item.boringButton != (Object)null) { return item; } } } return null; } private static int LastAudioSibling(SettingsCatagory category) { int num = 0; foreach (SettingsRow item in (Il2CppArrayBase)(object)category.rows) { if ((Object)(object)item != (Object)null) { num = Math.Max(num, ((Component)item).transform.GetSiblingIndex()); } } return num; } private static SettingsRow CloneRow(SettingsRow template, Transform parent, int sibling, string name) { GameObject obj = Object.Instantiate(((Component)template).gameObject, parent); ((Object)obj).name = name; obj.transform.SetSiblingIndex(sibling); obj.SetActive(true); SettingsRow component = obj.GetComponent(); ((Behaviour)component).enabled = false; component.settingsMenu = template.settingsMenu; return component; } private static void ConfigureCycleRow(SettingsRow row, string title, Func value, Action change) { SetRowTitle(row, title); SetRaw(row.arrayLabel, value()); Wire(row.leftButton, delegate { change(-1); }); Wire(row.rightButton, delegate { change(1); }); } private static void ConfigureButtonRow(SettingsRow row, string title, string buttonText, Action action) { SetRowTitle(row, title); SetButtonText(row.boringButton, buttonText); Wire(row.boringButton, action); } private static void ConfigureSliderRow(SettingsRow row, string title, float value, Action change) { SetRowTitle(row, title); row.slider.minValue = 1f; row.slider.maxValue = 20f; row.slider.wholeNumbers = true; row.slider.SetValueWithoutNotify(Mathf.Round(value)); SetRaw(row.sliderLabel, $"×{Mathf.RoundToInt(value)}"); int persistentEventCount = ((UnityEventBase)row.slider.onValueChanged).GetPersistentEventCount(); for (int i = 0; i < persistentEventCount; i++) { ((UnityEventBase)row.slider.onValueChanged).SetPersistentListenerState(i, (UnityEventCallState)0); } ((UnityEventBase)row.slider.onValueChanged).RemoveAllListeners(); ((UnityEvent)(object)row.slider.onValueChanged).AddListener(DelegateSupport.ConvertDelegate>((Delegate)change)); } private static void Wire(Button button, Action callback) { if (!((Object)(object)button == (Object)null)) { int persistentEventCount = ((UnityEventBase)button.onClick).GetPersistentEventCount(); for (int i = 0; i < persistentEventCount; i++) { ((UnityEventBase)button.onClick).SetPersistentListenerState(i, (UnityEventCallState)0); } ((UnityEventBase)button.onClick).RemoveAllListeners(); ((UnityEvent)button.onClick).AddListener(DelegateSupport.ConvertDelegate((Delegate)callback)); } } private static void Refresh(SettingsMenu menu) { if (!((Object)(object)menu == (Object)null)) { SetCycleTitle(((Component)menu).transform, "BigWalk.VoiceSettings.Native.Positioning", "VOICE POSITIONING"); SetCycleValue(((Component)menu).transform, "BigWalk.VoiceSettings.Native.Positioning", Plugin.Instance.TwoDVoice.Value ? "2D EVERYWHERE" : "3D SPATIAL"); SetCycleTitle(((Component)menu).transform, "BigWalk.VoiceSettings.Native.Range", "PROXIMITY RANGE"); SetRangeValue(((Component)menu).transform); SetCycleTitle(((Component)menu).transform, "BigWalk.VoiceSettings.Native.Indicators", "SPEAKER INDICATORS"); SetCycleValue(((Component)menu).transform, "BigWalk.VoiceSettings.Native.Indicators", IndicatorLabel()); SetCycleTitle(((Component)menu).transform, "BigWalk.VoiceSettings.Native.Advanced", "BETTER PROXIMITY VOICE"); Transform obj = FindDescendant(((Component)menu).transform, "BigWalk.VoiceSettings.Native.Advanced"); SettingsRow val = ((obj != null) ? ((Component)obj).GetComponent() : null); if ((Object)(object)((val != null) ? val.boringButton : null) != (Object)null) { SetButtonText(val.boringButton, "ADVANCED SETTINGS"); } else if ((Object)(object)((val != null) ? val.arrayLabel : null) != (Object)null) { SetRaw(val.arrayLabel, "OPEN"); } } } private static void SetCycleTitle(Transform menu, string name, string value) { Transform obj = FindDescendant(menu, name); SettingsRow val = ((obj != null) ? ((Component)obj).GetComponent() : null); if (!((Object)(object)val == (Object)null)) { SetRowTitle(val, value); } } private static void SetCycleValue(Transform menu, string name, string value) { Transform obj = FindDescendant(menu, name); SettingsRow val = ((obj != null) ? ((Component)obj).GetComponent() : null); if ((Object)(object)((val != null) ? val.arrayLabel : null) != (Object)null) { SetRaw(val.arrayLabel, value); } } private static void SetRangeValue(Transform menu) { Transform obj = FindDescendant(menu, "BigWalk.VoiceSettings.Native.Range"); SettingsRow val = ((obj != null) ? ((Component)obj).GetComponent() : null); if (!((Object)(object)val == (Object)null)) { if ((Object)(object)val.slider != (Object)null) { float num = Mathf.Clamp(Plugin.Instance.RangeMultiplier.Value, 1f, 20f); val.slider.SetValueWithoutNotify(Mathf.Round(num)); SetRaw(val.sliderLabel, $"×{num:0.##}"); } else if ((Object)(object)val.arrayLabel != (Object)null) { SetRaw(val.arrayLabel, RangeLabel()); } } } private static Transform FindDescendant(Transform root, string name) { if ((Object)(object)root == (Object)null) { return null; } foreach (Transform componentsInChild in ((Component)root).GetComponentsInChildren(true)) { if ((Object)(object)componentsInChild != (Object)null && ((Object)((Component)componentsInChild).gameObject).name == name) { return componentsInChild; } } return null; } private static void RebuildNavigation(SettingsCatagory category, List customRows) { List list = new List(); foreach (SettingsRow item in (Il2CppArrayBase)(object)category.rows) { if ((Object)(object)item != (Object)null) { list.Add(item); } } list.AddRange(customRows); for (int i = 0; i < list.Count; i++) { SettingsRow val = ((i == 0) ? null : list[i - 1]); SettingsRow val2 = ((i == list.Count - 1) ? null : list[i + 1]); list[i].SetNavigation(val, val2); } } private static void ApplyAndRefresh() { Plugin.Instance.Overlay.ApplyImmediately(); Refresh(); } private static string RangeLabel() { float value = Plugin.Instance.RangeMultiplier.Value; int num = ClosestRangeIndex(value); if (!(Mathf.Abs(RangePresets[num] - value) < 0.01f)) { return $"CUSTOM ×{value:0.##}"; } return RangeLabels[num]; } private static int ClosestRangeIndex(float value) { int result = 0; float num = float.MaxValue; for (int i = 0; i < RangePresets.Length; i++) { float num2 = Mathf.Abs(RangePresets[i] - value); if (!(num2 >= num)) { num = num2; result = i; } } return result; } private static int IndicatorIndex() { if (!Plugin.Instance.SpeakerIndicators.Value) { return 0; } if (!Plugin.Instance.ActiveSpeakerRoster.Value) { return 1; } return 2; } private static string IndicatorLabel() { return IndicatorIndex() switch { 0 => "OFF", 1 => "ICONS", _ => "ICONS + ROSTER", }; } private static void SetIndicatorIndex(int index) { Plugin.Instance.SpeakerIndicators.Value = index != 0; Plugin.Instance.ActiveSpeakerRoster.Value = index == 2; } private static void SetRaw(LocalizedText localized, string value) { if ((Object)(object)localized == (Object)null) { return; } localized.displayType = (DisplayType)1; localized.rawValue = value; localized.Change(value, (DisplayType)1); if ((Object)(object)localized.textElement != (Object)null) { localized.textElement.text = value; } foreach (TMP_Text componentsInChild in ((Component)localized).GetComponentsInChildren(true)) { if ((Object)(object)componentsInChild != (Object)null) { componentsInChild.text = value; } } } private static void SetRowTitle(SettingsRow row, string value) { if ((Object)(object)row == (Object)null) { return; } SetRaw(row.title, value); LocalizedText arrayLabel = row.arrayLabel; TMP_Text val = ((arrayLabel != null) ? arrayLabel.textElement : null); LocalizedText sliderLabel = row.sliderLabel; TMP_Text val2 = ((sliderLabel != null) ? sliderLabel.textElement : null); foreach (TMP_Text componentsInChild in ((Component)row).GetComponentsInChildren(true)) { if ((Object)(object)componentsInChild == (Object)null || (Object)(object)componentsInChild == (Object)(object)val || (Object)(object)componentsInChild == (Object)(object)val2) { continue; } Transform transform = componentsInChild.transform; Button leftButton = row.leftButton; if (IsWithin(transform, (leftButton != null) ? ((Component)leftButton).transform : null)) { continue; } Transform transform2 = componentsInChild.transform; Button rightButton = row.rightButton; if (IsWithin(transform2, (rightButton != null) ? ((Component)rightButton).transform : null)) { continue; } Transform transform3 = componentsInChild.transform; Button boringButton = row.boringButton; if (!IsWithin(transform3, (boringButton != null) ? ((Component)boringButton).transform : null)) { LocalizedText component = ((Component)componentsInChild).GetComponent(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = false; component.displayType = (DisplayType)1; component.rawValue = value; } componentsInChild.text = value; } } } private static bool IsWithin(Transform candidate, Transform ancestor) { if ((Object)(object)candidate == (Object)null || (Object)(object)ancestor == (Object)null) { return false; } Transform val = candidate; while ((Object)(object)val != (Object)null) { if ((Object)(object)val == (Object)(object)ancestor) { return true; } val = val.parent; } return false; } private static void SetButtonText(Button button, string value) { TMP_Text val = ((button != null) ? ((Component)button).GetComponentInChildren(true) : null); if (!((Object)(object)val == (Object)null)) { LocalizedText component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { SetRaw(component, value); } else { val.text = value; } } } private static void EnsureScroller(SettingsMenu menu, Transform contentTransform) { int instanceID = ((Object)menu).GetInstanceID(); if (!Scrollers.ContainsKey(instanceID)) { RectTransform val = AsRect(contentTransform); RectTransform val2 = AsRect(menu.contents); if ((Object)(object)val2 == (Object)null || (Object)(object)val2 == (Object)(object)val) { val2 = AsRect((contentTransform != null) ? contentTransform.parent : null); } if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)val)) { Scrollers[instanceID] = new AudioScrollState(menu, val, val2); } } } private static RectTransform AsRect(Transform transform) { if ((Object)(object)transform == (Object)null) { return null; } RectTransform val = ((Il2CppObjectBase)transform).TryCast(); if (!((Object)(object)val != (Object)null)) { return ((Component)transform).GetComponent(); } return val; } internal static bool IsCustomRow(SettingsRow row) { if ((Object)(object)row != (Object)null) { return ((Object)((Component)row).gameObject).name.StartsWith("BigWalk.VoiceSettings.Native.", StringComparison.Ordinal); } return false; } internal static void ResetToDefaults() { Plugin.Instance.RangeMultiplier.Value = 1f; Plugin.Instance.TwoDVoice.Value = false; Plugin.Instance.SpeakerIndicators.Value = true; Plugin.Instance.SpeakerNames.Value = true; Plugin.Instance.ActiveSpeakerRoster.Value = true; Plugin.Instance.SpeakerDistances.Value = true; Plugin.Instance.HudScale.Value = 1f; Plugin.Instance.TalkThreshold.Value = 0.004f; Plugin.Instance.Overlay.ApplyImmediately(); Refresh(); } } [HarmonyPatch(typeof(SettingsMenu), "ActionResetAudio")] internal static class AudioResetPatch { private static void Postfix() { NativeSettingsIntegration.ResetToDefaults(); } } [HarmonyPatch(typeof(SettingsRow), "Refresh")] internal static class CustomSettingsRowRefreshPatch { private static bool Prefix(SettingsRow __instance) { if (!NativeSettingsIntegration.IsCustomRow(__instance)) { return true; } NativeSettingsIntegration.Refresh(); return false; } } internal static class PlayerVoiceInfo { public static string DisplayName(PlayerVoicePlaybackControl control, int fallbackIndex = 0) { try { object obj; if (control == null) { obj = null; } else { PlayerCharacter playerCharacter = control.playerCharacter; obj = ((playerCharacter != null) ? playerCharacter.playerNetworking : null); } PlayerNetworking val = (PlayerNetworking)obj; if ((Object)(object)val != (Object)null) { string text = FirstUseful(val.moderationNameSanitized, val.moderationName, val.username); if (text != null) { return text; } } string text2 = ((control != null) ? control.XProviderIdentifier : null); if (!string.IsNullOrWhiteSpace(text2)) { return text2; } } catch { } if (fallbackIndex <= 0) { return "Unknown player"; } return $"Player {fallbackIndex}"; } public static Transform Anchor(PlayerVoicePlaybackControl control) { if ((Object)(object)control == (Object)null) { return null; } if (!((Object)(object)control.playerCharacter != (Object)null)) { return ((Component)control).transform; } return ((Component)control.playerCharacter).transform; } public static float DistanceFromCamera(PlayerVoicePlaybackControl control) { //IL_002b: 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) Camera main = Camera.main; Transform val = Anchor(control); if (!((Object)(object)main != (Object)null) || !((Object)(object)val != (Object)null)) { return -1f; } return Vector3.Distance(((Component)main).transform.position, val.position); } public static float AudibleRange(PlayerVoicePlaybackControl control) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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) //IL_0054: 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) AnimationCurve val = ((control != null) ? control.AttenuationCurve : null); if (val == null) { return 0f; } Il2CppStructArray keys = val.keys; if (keys == null || ((Il2CppArrayBase)(object)keys).Length == 0) { return 0f; } Keyframe val2; for (int i = 0; i < ((Il2CppArrayBase)(object)keys).Length; i++) { val2 = ((Il2CppArrayBase)(object)keys)[i]; if (Mathf.Abs(((Keyframe)(ref val2)).value) < 0.0001f) { val2 = ((Il2CppArrayBase)(object)keys)[i]; if (((Keyframe)(ref val2)).time > 0f) { val2 = ((Il2CppArrayBase)(object)keys)[i]; return ((Keyframe)(ref val2)).time; } } } val2 = ((Il2CppArrayBase)(object)keys)[((Il2CppArrayBase)(object)keys).Length - 1]; return ((Keyframe)(ref val2)).time; } private static string FirstUseful(params string[] candidates) { foreach (string text in candidates) { if (!string.IsNullOrWhiteSpace(text)) { return text.Trim(); } } return null; } } [BepInPlugin("com.bigwalk.voicesettings", "Better Proximity Voice", "1.4.0")] public class Plugin : BasePlugin { public const string Guid = "com.bigwalk.voicesettings"; public const string Version = "1.4.0"; internal static Plugin Instance { get; private set; } internal static ManualLogSource Trace { get; private set; } internal ConfigEntry MenuShortcut { get; private set; } internal ConfigEntry ToggleTwoDShortcut { get; private set; } internal ConfigEntry CycleRangeShortcut { get; private set; } internal ConfigEntry ToggleHudShortcut { get; private set; } internal ConfigEntry FreeCursor { get; private set; } internal ConfigEntry RangeMultiplier { get; private set; } internal ConfigEntry TwoDVoice { get; private set; } internal ConfigEntry SpeakerIndicators { get; private set; } internal ConfigEntry SpeakerNames { get; private set; } internal ConfigEntry ActiveSpeakerRoster { get; private set; } internal ConfigEntry SpeakerDistances { get; private set; } internal ConfigEntry HudScale { get; private set; } internal ConfigEntry TalkThreshold { get; private set; } internal VoiceSettingsOverlay Overlay { get; private set; } public override void Load() { //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Expected O, but got Unknown //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Expected O, but got Unknown Instance = this; Trace = ((BasePlugin)this).Log; MenuShortcut = ((BasePlugin)this).Config.Bind("Shortcuts", "OpenMenu", "LeftAlt + V", "Shows or hides Advanced Voice Settings. Core controls also appear in Settings > Audio."); ToggleTwoDShortcut = ((BasePlugin)this).Config.Bind("Shortcuts", "ToggleAudioMode", "Not bound", "Optionally switches between positional 3D voice and non-positional 2D voice."); CycleRangeShortcut = ((BasePlugin)this).Config.Bind("Shortcuts", "CycleRange", "Not bound", "Optionally cycles the voice-range presets: x1, x2, x5, x10, and x20."); ToggleHudShortcut = ((BasePlugin)this).Config.Bind("Shortcuts", "ToggleHud", "Not bound", "Optionally shows or hides all speaker HUD elements."); FreeCursor = ((BasePlugin)this).Config.Bind("Menu", "FreeCursorWhenOpen", true, "Unlocks and shows the mouse cursor while the voice settings menu is open."); RangeMultiplier = ((BasePlugin)this).Config.Bind("Voice", "RangeMultiplier", 1f, "Multiplies the distance over which you hear other players (1-20). This changes only your local playback."); TwoDVoice = ((BasePlugin)this).Config.Bind("Voice", "TwoDVoice", false, "Plays every received voice non-positionally and without distance attenuation."); SpeakerIndicators = ((BasePlugin)this).Config.Bind("Indicators", "Enabled", true, "Draws an icon over every remote player currently speaking."); SpeakerNames = ((BasePlugin)this).Config.Bind("Indicators", "ShowNames", true, "Shows each speaking player's display name beside their world indicator."); ActiveSpeakerRoster = ((BasePlugin)this).Config.Bind("Indicators", "ActiveSpeakerRoster", true, "Shows a compact roster of current speakers in the lower-right corner."); SpeakerDistances = ((BasePlugin)this).Config.Bind("Indicators", "ShowDistance", true, "Shows distance in metres beside each speaking player's name."); HudScale = ((BasePlugin)this).Config.Bind("Indicators", "HudScale", 1f, "Scales speaker indicators and the active-speaker roster (0.75-1.5)."); TalkThreshold = ((BasePlugin)this).Config.Bind("Indicators", "TalkThreshold", 0.004f, "Minimum smoothed voice amplitude treated as speech. Lower this if quiet speakers do not light up; raise it if icons appear because of background noise."); RangeMultiplier.Value = Mathf.Clamp(RangeMultiplier.Value, 1f, 20f); HudScale.Value = Mathf.Clamp(HudScale.Value, 0.75f, 1.5f); TalkThreshold.Value = Mathf.Clamp(TalkThreshold.Value, 0.0001f, 0.1f); ClassInjector.RegisterTypeInIl2Cpp(); new Harmony("com.bigwalk.voicesettings").PatchAll(typeof(Plugin).Assembly); GameObject val = new GameObject("BigWalk.VoiceSettings"); ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val); Overlay = val.AddComponent(); ManualLogSource log = ((BasePlugin)this).Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(77, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Loaded. Native controls appear in Settings > Audio; "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(MenuShortcut.Value); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" opens advanced settings."); } log.LogInfo(val2); } } internal static class ShortcutBinding { private readonly struct Parsed { public KeyCode MainKey { get; } public KeyCode[] Modifiers { get; } public string Display { get; } public Parsed(KeyCode mainKey, KeyCode[] modifiers, string display) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) MainKey = mainKey; Modifiers = modifiers; Display = display; } } private static readonly HashSet ModifierKeys = new HashSet { (KeyCode)308, (KeyCode)307, (KeyCode)306, (KeyCode)305, (KeyCode)304, (KeyCode)303, (KeyCode)310, (KeyCode)309, (KeyCode)311, (KeyCode)312 }; public static bool IsDown(string value) { //IL_000c: 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) if (!TryParse(value, out var parsed) || (int)parsed.MainKey == 0) { return false; } if (!Input.GetKeyDown(parsed.MainKey)) { return false; } KeyCode[] modifiers = parsed.Modifiers; for (int i = 0; i < modifiers.Length; i++) { if (!Input.GetKey(modifiers[i])) { return false; } } return true; } public static bool IsBound(string value) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 if (TryParse(value, out var parsed)) { return (int)parsed.MainKey > 0; } return false; } public static bool IsValid(string value) { Parsed parsed; return TryParse(value, out parsed); } public static string Display(string value) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (!TryParse(value, out var parsed)) { return "Invalid (" + value + ")"; } if ((int)parsed.MainKey != 0) { return parsed.Display; } return "Not bound"; } public static bool Equivalent(string left, string right) { if (!TryParse(left, out var parsed) || !TryParse(right, out var parsed2)) { return false; } return string.Equals(parsed.Display, parsed2.Display, StringComparison.OrdinalIgnoreCase); } private unsafe static bool TryParse(string value, out Parsed parsed) { //IL_0056: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: 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) parsed = new Parsed((KeyCode)0, Array.Empty(), "Not bound"); if (string.IsNullOrWhiteSpace(value) || value.Trim().Equals("Not bound", StringComparison.OrdinalIgnoreCase) || value.Trim().Equals("None", StringComparison.OrdinalIgnoreCase)) { return true; } string[] array = value.Split('+', StringSplitOptions.RemoveEmptyEntries); List list = new List(); KeyCode val = (KeyCode)0; string[] array2 = array; for (int i = 0; i < array2.Length; i++) { if (!Enum.TryParse(ExpandAlias(array2[i].Trim()), ignoreCase: true, out KeyCode result) || (int)result == 0) { return false; } if (ModifierKeys.Contains(result)) { if (!list.Contains(result)) { list.Add(result); } continue; } if ((int)val == 0) { val = result; continue; } return false; } if ((int)val == 0) { return false; } list.Sort((KeyCode left, KeyCode right) => ((int)left).CompareTo((int)right)); List list2 = new List(); foreach (KeyCode item in list) { list2.Add(((object)item/*cast due to .constrained prefix*/).ToString()); } list2.Add(((object)(*(KeyCode*)(&val))/*cast due to .constrained prefix*/).ToString()); parsed = new Parsed(val, list.ToArray(), string.Join(" + ", list2)); return true; } private static string ExpandAlias(string token) { if (token.Equals("Alt", StringComparison.OrdinalIgnoreCase)) { return "LeftAlt"; } if (token.Equals("Ctrl", StringComparison.OrdinalIgnoreCase) || token.Equals("Control", StringComparison.OrdinalIgnoreCase)) { return "LeftControl"; } if (token.Equals("Shift", StringComparison.OrdinalIgnoreCase)) { return "LeftShift"; } if (token.Equals("Cmd", StringComparison.OrdinalIgnoreCase) || token.Equals("Command", StringComparison.OrdinalIgnoreCase)) { return "LeftCommand"; } return token; } } internal static class SpeakerIndicators { private sealed class ActiveSpeaker { public string Name; public float Level; public float Distance; } private const float BarGain = 12f; private const float HeadHeight = 2.4f; private static readonly List ActiveSpeakers = new List(); private static Texture2D _pixel; private static GUIStyle _nameStyle; private static GUIStyle _rosterNameStyle; private static GUIStyle _rosterHeadingStyle; private static float _styledScale = -1f; private static Texture2D Pixel { get { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_pixel != (Object)null) { return _pixel; } _pixel = new Texture2D(1, 1, (TextureFormat)4, false); _pixel.SetPixel(0, 0, Color.white); _pixel.Apply(); ((Object)_pixel).hideFlags = (HideFlags)61; return _pixel; } } public static bool IsTalking(PlayerVoicePlaybackControl control) { if ((Object)(object)control == (Object)null) { return false; } float num = Mathf.Clamp(Plugin.Instance.TalkThreshold.Value, 0.0001f, 0.1f); return control.SmoothedARV >= num; } public static void Draw() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Expected O, but got Unknown //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) Color color = GUI.color; try { Camera main = Camera.main; List controls = PlayerVoicePlaybackControl.controls; if ((Object)(object)main == (Object)null || controls == null) { return; } float scale = Mathf.Clamp(Plugin.Instance.HudScale.Value, 0.75f, 1.5f); EnsureStyles(scale); ActiveSpeakers.Clear(); Vector3 position = ((Component)main).transform.position; int num = 0; Enumerator enumerator = controls.GetEnumerator(); while (enumerator.MoveNext()) { PlayerVoicePlaybackControl current = enumerator.Current; if ((Object)(object)current == (Object)null) { continue; } num++; if (IsTalking(current)) { Transform val = PlayerVoiceInfo.Anchor(current); if (!((Object)(object)val == (Object)null)) { float level = Mathf.Clamp01(current.SmoothedARV * 12f); float num2 = Vector3.Distance(position, val.position); string name = PlayerVoiceInfo.DisplayName(current, num); Vector3 world = val.position + Vector3.up * 2.4f; float num3 = PlayerVoiceInfo.AudibleRange(current); float distanceRatio = ((num3 > 0f) ? Mathf.Clamp01(num2 / num3) : 0f); DrawMarker(main, world, distanceRatio, level, name, num2, scale); ActiveSpeakers.Add(new ActiveSpeaker { Name = name, Level = level, Distance = num2 }); } } } if (Plugin.Instance.ActiveSpeakerRoster.Value && ActiveSpeakers.Count > 0) { ActiveSpeakers.Sort((ActiveSpeaker left, ActiveSpeaker right) => right.Level.CompareTo(left.Level)); DrawRoster(scale); } } catch (Exception ex) { ManualLogSource trace = Plugin.Trace; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(27, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Speaker indicators failed: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex); } trace.LogError(val2); } finally { GUI.color = color; } } private static void DrawMarker(Camera camera, Vector3 world, float distanceRatio, float level, string name, float distance, float scale) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_0098: 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_00b8: 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) Vector3 val = camera.WorldToScreenPoint(world); bool num = val.z <= 0f; float num2 = 32f * scale; float num3 = (num ? ((float)Screen.width - val.x) : val.x); float num4 = (num ? 0f : ((float)Screen.height - val.y)); bool offScreen = num || num3 < num2 || num3 > (float)Screen.width - num2 || num4 < num2 || num4 > (float)Screen.height - num2; num3 = Mathf.Clamp(num3, num2, (float)Screen.width - num2); num4 = Mathf.Clamp(num4, num2, (float)Screen.height - num2); Color colour = DistanceColour(distanceRatio); colour.a = Mathf.Lerp(1f, 0.42f, distanceRatio); DrawSpeaker(num3, num4, colour, level, offScreen, scale); if (Plugin.Instance.SpeakerNames.Value) { DrawName(num3, num4, name, distance, colour, scale); } } private static void DrawSpeaker(float centreX, float centreY, Color colour, float level, bool offScreen, float scale) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) GUI.color = new Color(0.025f, 0.03f, 0.035f, colour.a * 0.92f); Fill(centreX - 14f * scale, centreY - 12f * scale, 31f * scale, 24f * scale); GUI.color = colour; Fill(centreX - 10f * scale, centreY - 3f * scale, 4f * scale, 6f * scale); Fill(centreX - 6f * scale, centreY - 5f * scale, 2f * scale, 10f * scale); Fill(centreX - 4f * scale, centreY - 7f * scale, 2f * scale, 14f * scale); Fill(centreX - 2f * scale, centreY - 9f * scale, 2f * scale, 18f * scale); for (int i = 0; i < 3; i++) { Color color = colour; if (level < 0.15f + (float)i * 0.28f) { color.a *= 0.18f; } GUI.color = color; float num = (6f + (float)i * 4f) * scale; Fill(centreX + (3f + (float)i * 4f) * scale, centreY - num * 0.5f, 2f * scale, num); } if (offScreen) { GUI.color = colour; Fill(centreX - 8f * scale, centreY + 15f * scale, 16f * scale, 2f * scale); } } private static void DrawName(float markerX, float markerY, string name, float distance, Color colour, float scale) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_005d: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) GUIContent val = new GUIContent(Plugin.Instance.SpeakerDistances.Value ? $"{name} · {distance:0} m" : name); float num = Mathf.Min(_nameStyle.CalcSize(val).x + 18f * scale, 260f * scale); float num2 = 27f * scale; float num3 = markerX + 21f * scale; if (num3 + num > (float)Screen.width - 12f * scale) { num3 = markerX - num - 21f * scale; } float num4 = markerY - num2 * 0.5f; GUI.color = new Color(0.025f, 0.03f, 0.035f, 0.88f); Fill(num3, num4, num, num2); GUI.color = colour; Fill(num3, num4, 3f * scale, num2); GUI.color = Color.white; GUI.Label(new Rect(num3 + 10f * scale, num4, num - 14f * scale, num2), val, _nameStyle); } private static void DrawRoster(float scale) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_017d: 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_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Min(ActiveSpeakers.Count, 6); float num2 = 270f * scale; float num3 = 29f * scale; float num4 = 34f * scale; float num5 = num3 + (float)num * num4 + 8f * scale; float num6 = (float)Screen.width - num2 - 24f * scale; float num7 = (float)Screen.height - num5 - 24f * scale; GUI.color = new Color(0.025f, 0.03f, 0.035f, 0.88f); Fill(num6, num7, num2, num5); GUI.color = new Color(0.35f, 0.9f, 0.58f, 1f); Fill(num6, num7, 4f * scale, num5); GUI.color = Color.white; GUI.Label(new Rect(num6 + 13f * scale, num7, num2 - 20f * scale, num3), "NOW SPEAKING", _rosterHeadingStyle); for (int i = 0; i < num; i++) { ActiveSpeaker activeSpeaker = ActiveSpeakers[i]; float num8 = num7 + num3 + (float)i * num4; string text = (Plugin.Instance.SpeakerDistances.Value ? $"{activeSpeaker.Distance:0} m" : ""); GUI.color = Color.white; GUI.Label(new Rect(num6 + 13f * scale, num8, num2 - 75f * scale, 22f * scale), activeSpeaker.Name, _rosterNameStyle); GUI.Label(new Rect(num6 + num2 - 65f * scale, num8, 52f * scale, 22f * scale), text, _rosterNameStyle); GUI.color = new Color(1f, 1f, 1f, 0.15f); Fill(num6 + 13f * scale, num8 + 23f * scale, num2 - 26f * scale, 3f * scale); GUI.color = DistanceColour(1f - activeSpeaker.Level); Fill(num6 + 13f * scale, num8 + 23f * scale, (num2 - 26f * scale) * Mathf.Max(0.05f, activeSpeaker.Level), 3f * scale); } } private static Color DistanceColour(float ratio) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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) ratio = Mathf.Clamp01(ratio); if (!(ratio < 0.5f)) { return Color.Lerp(new Color(1f, 0.85f, 0.2f), new Color(1f, 0.25f, 0.2f), (ratio - 0.5f) * 2f); } return Color.Lerp(new Color(0.3f, 1f, 0.35f), new Color(1f, 0.85f, 0.2f), ratio * 2f); } private static void EnsureStyles(float scale) { if (_nameStyle == null || !Mathf.Approximately(scale, _styledScale)) { _styledScale = scale; _nameStyle = NewLabel(Mathf.RoundToInt(14f * scale), (FontStyle)1, (TextAnchor)3); _rosterNameStyle = NewLabel(Mathf.RoundToInt(13f * scale), (FontStyle)0, (TextAnchor)0); _rosterHeadingStyle = NewLabel(Mathf.RoundToInt(12f * scale), (FontStyle)1, (TextAnchor)3); } } private static GUIStyle NewLabel(int fontSize, FontStyle fontStyle, TextAnchor alignment) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_0017: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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) //IL_003c: Expected O, but got Unknown GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = fontSize, fontStyle = fontStyle, alignment = alignment, clipping = (TextClipping)1 }; val.normal.textColor = Color.white; return val; } private static void Fill(float x, float y, float width, float height) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) GUI.DrawTexture(new Rect(x, y, width, height), (Texture)(object)Pixel); } } internal static class VoiceRangeScaler { private sealed class Baseline { public Keyframe[] Attenuation; public Keyframe[] SpatialVolume; public Keyframe[] FilterDistance; public float SourceMaxDistance = -1f; } public const float MaxScale = 20f; private static readonly Dictionary Baselines = new Dictionary(); private static float _scale = 1f; public static float Scale { get { return _scale; } set { _scale = Mathf.Clamp(value, 1f, 20f); } } public static int LastApplied { get; private set; } public static void Apply() { List controls = PlayerVoicePlaybackControl.controls; LastApplied = 0; if (controls == null) { return; } HashSet hashSet = new HashSet(); Enumerator enumerator = controls.GetEnumerator(); while (enumerator.MoveNext()) { PlayerVoicePlaybackControl current = enumerator.Current; if (!((Object)(object)current == (Object)null)) { int instanceID = ((Object)current).GetInstanceID(); hashSet.Add(instanceID); if (!Baselines.TryGetValue(instanceID, out var value)) { value = Capture(current); Baselines[instanceID] = value; } current.AttenuationCurve = Rescale(value.Attenuation, _scale); current.SpatialVolCurve = Rescale(value.SpatialVolume, _scale); current.FilterDistanceCurve = Rescale(value.FilterDistance, _scale); AudioSource val = SourceOf(current); if (value.SourceMaxDistance <= 0f && (Object)(object)val != (Object)null) { value.SourceMaxDistance = val.maxDistance; } if (value.SourceMaxDistance > 0f && (Object)(object)val != (Object)null) { val.maxDistance = value.SourceMaxDistance * _scale; } LastApplied++; } } if (Baselines.Count <= hashSet.Count) { return; } List list = new List(); foreach (KeyValuePair baseline in Baselines) { if (!hashSet.Contains(baseline.Key)) { list.Add(baseline.Key); } } foreach (int item in list) { Baselines.Remove(item); } } private static Baseline Capture(PlayerVoicePlaybackControl control) { Baseline baseline = new Baseline { Attenuation = Copy(control.AttenuationCurve), SpatialVolume = Copy(control.SpatialVolCurve), FilterDistance = Copy(control.FilterDistanceCurve) }; AudioSource val = SourceOf(control); if ((Object)(object)val != (Object)null) { baseline.SourceMaxDistance = val.maxDistance; } return baseline; } private static AudioSource SourceOf(PlayerVoicePlaybackControl control) { try { AudioSourceController sourceController = control.SourceController; return ((Object)(object)sourceController != (Object)null) ? sourceController.AudioSource : null; } catch { return null; } } private static Keyframe[] Copy(AnimationCurve curve) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (curve == null) { return null; } Il2CppStructArray keys = curve.keys; if (keys == null || ((Il2CppArrayBase)(object)keys).Length == 0) { return null; } Keyframe[] array = (Keyframe[])(object)new Keyframe[((Il2CppArrayBase)(object)keys).Length]; for (int i = 0; i < ((Il2CppArrayBase)(object)keys).Length; i++) { array[i] = ((Il2CppArrayBase)(object)keys)[i]; } return array; } private static AnimationCurve Rescale(Keyframe[] baseline, float scale) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown if (baseline == null || baseline.Length == 0) { return null; } Il2CppStructArray val = new Il2CppStructArray((long)baseline.Length); for (int i = 0; i < baseline.Length; i++) { Keyframe val2 = baseline[i]; ((Keyframe)(ref val2)).time = ((Keyframe)(ref val2)).time * scale; ((Keyframe)(ref val2)).inTangent = ((Keyframe)(ref val2)).inTangent / scale; ((Keyframe)(ref val2)).outTangent = ((Keyframe)(ref val2)).outTangent / scale; ((Il2CppArrayBase)(object)val)[i] = val2; } return new AnimationCurve(val); } } public class VoiceSettingsOverlay : MonoBehaviour { private enum ShortcutSlot { None, Menu, AudioMode, Range, Hud } private const float ApplyInterval = 1f; private static readonly float[] RangePresets = new float[5] { 1f, 2f, 5f, 10f, 20f }; private bool _visible; private Rect _window = new Rect(24f, 24f, 620f, 480f); private Vector2 _scroll; private CursorLockMode _previousLockState = (CursorLockMode)1; private bool _previousCursorVisible; private float _nextApply; private string _rangeText; private string _status = "Waiting for a world…"; private string _toastTitle; private string _toastDetail; private float _toastUntil; private ShortcutSlot _capturingShortcut; private SettingsMenu _returnToSettingsMenu; private Texture2D _panelTexture; private Texture2D _accentTexture; private GUIStyle _windowStyle; private GUIStyle _headingStyle; private GUIStyle _labelStyle; private GUIStyle _mutedLabelStyle; private GUIStyle _buttonStyle; private GUIStyle _selectedButtonStyle; private GUIStyle _toggleStyle; private GUIStyle _textFieldStyle; private GUIStyle _toastTitleStyle; public VoiceSettingsOverlay(IntPtr pointer) : base(pointer) { }//IL_0015: 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) //IL_0021: Unknown result type (might be due to invalid IL or missing references) private void Start() { ApplySettings(); } private void Update() { NativeSettingsIntegration.Tick(); if (_capturingShortcut == ShortcutSlot.None) { if (_visible && Input.GetKeyDown((KeyCode)27)) { SetVisible(visible: false); return; } if (ShortcutBinding.IsDown(Plugin.Instance.MenuShortcut.Value)) { SetVisible(!_visible); } if (ShortcutBinding.IsDown(Plugin.Instance.ToggleTwoDShortcut.Value)) { SetTwoD(!Plugin.Instance.TwoDVoice.Value, notify: true); } if (ShortcutBinding.IsDown(Plugin.Instance.CycleRangeShortcut.Value)) { CycleRange(); } if (ShortcutBinding.IsDown(Plugin.Instance.ToggleHudShortcut.Value)) { Plugin.Instance.SpeakerIndicators.Value = !Plugin.Instance.SpeakerIndicators.Value; ShowToast(Plugin.Instance.SpeakerIndicators.Value ? "SPEAKER HUD ON" : "SPEAKER HUD OFF", Plugin.Instance.SpeakerIndicators.Value ? "Named talker indicators are visible." : "All speaker overlays are hidden."); } } if (_visible && Plugin.Instance.FreeCursor.Value) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } if (!(Time.unscaledTime < _nextApply)) { _nextApply = Time.unscaledTime + 1f; NativeSettingsIntegration.Ensure(); ApplySettings(); } } private void OnGUI() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_0062: 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) if (Plugin.Instance.SpeakerIndicators.Value && (int)Event.current.type == 7) { SpeakerIndicators.Draw(); } if (_visible || !(Time.unscaledTime >= _toastUntil)) { EnsureStyles(); if (Time.unscaledTime < _toastUntil) { DrawToast(); } if (_visible) { _window = GUI.Window(45430, _window, WindowFunction.op_Implicit((Action)DrawWindow), "Better Proximity Voice", _windowStyle); } } } private void DrawWindow(int windowId) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_003c: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_077a: Unknown result type (might be due to invalid IL or missing references) Color color = GUI.color; GUI.color = Color.white; GUI.DrawTexture(new Rect(5f, 24f, ((Rect)(ref _window)).width - 10f, ((Rect)(ref _window)).height - 29f), (Texture)(object)_panelTexture); HandleShortcutCapture(Event.current); _scroll = GUILayout.BeginScrollView(_scroll, (Il2CppReferenceArray)null); GUILayout.Label("Audio mode", _headingStyle, (Il2CppReferenceArray)null); GUILayout.Label("Choose positional awareness or maximum intelligibility.", _mutedLabelStyle, (Il2CppReferenceArray)null); GUILayout.BeginHorizontal((Il2CppReferenceArray)null); GUIStyle val = (Plugin.Instance.TwoDVoice.Value ? _buttonStyle : _selectedButtonStyle); GUIStyle val2 = (Plugin.Instance.TwoDVoice.Value ? _selectedButtonStyle : _buttonStyle); if (GUILayout.Button("3D SPATIAL\nDirection + distance", val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(52f) })) { SetTwoD(enabled: false, notify: true); } if (GUILayout.Button("2D EVERYWHERE\nCentred + no distance fade", val2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(52f) })) { SetTwoD(enabled: true, notify: true); } GUILayout.EndHorizontal(); GUILayout.Label("Hearing range", _headingStyle, (Il2CppReferenceArray)null); GUILayout.Label("Client-side only. Other players need no mod.", _mutedLabelStyle, (Il2CppReferenceArray)null); float scale = VoiceRangeScaler.Scale; float num = Mathf.Log(20f); float num2 = Mathf.Log(Mathf.Max(scale, 1f)) / num; GUILayout.BeginHorizontal((Il2CppReferenceArray)null); GUILayout.Label("Range ×", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(85f) }); float num3 = GUILayout.HorizontalSlider(num2, 0f, 1f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(350f) }); GUILayout.Label(scale.ToString("0.##"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(65f) }); GUILayout.EndHorizontal(); if (!Mathf.Approximately(num3, num2)) { SetRange(Mathf.Exp(num3 * num)); } GUILayout.BeginHorizontal((Il2CppReferenceArray)null); if (PresetButton("VANILLA", 1f)) { SetRange(1f, notify: true); } if (PresetButton("SOCIAL", 2f)) { SetRange(2f, notify: true); } if (PresetButton("WIDE", 5f)) { SetRange(5f, notify: true); } if (PresetButton("FAR", 10f)) { SetRange(10f, notify: true); } if (PresetButton("MAX", 20f)) { SetRange(20f, notify: true); } GUILayout.EndHorizontal(); GUILayout.Label(EffectiveRangeDescription(), _mutedLabelStyle, (Il2CppReferenceArray)null); GUILayout.BeginHorizontal((Il2CppReferenceArray)null); GUILayout.Label("Exact", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(85f) }); _rangeText = GUILayout.TextField(_rangeText ?? scale.ToString("0.##", CultureInfo.InvariantCulture), _textFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) }); if (GUILayout.Button("Apply", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) })) { if (float.TryParse(_rangeText, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { SetRange(result, notify: true); } else { _status = "'" + _rangeText + "' is not a number."; } } GUILayout.EndHorizontal(); GUILayout.Label("Speaker HUD", _headingStyle, (Il2CppReferenceArray)null); bool flag = GUILayout.Toggle(Plugin.Instance.SpeakerIndicators.Value, "Enabled", _toggleStyle, (Il2CppReferenceArray)null); if (flag != Plugin.Instance.SpeakerIndicators.Value) { Plugin.Instance.SpeakerIndicators.Value = flag; } bool flag2 = GUILayout.Toggle(Plugin.Instance.SpeakerNames.Value, "Names above talking players", _toggleStyle, (Il2CppReferenceArray)null); if (flag2 != Plugin.Instance.SpeakerNames.Value) { Plugin.Instance.SpeakerNames.Value = flag2; } bool flag3 = GUILayout.Toggle(Plugin.Instance.ActiveSpeakerRoster.Value, "Active-speaker roster", _toggleStyle, (Il2CppReferenceArray)null); if (flag3 != Plugin.Instance.ActiveSpeakerRoster.Value) { Plugin.Instance.ActiveSpeakerRoster.Value = flag3; } bool flag4 = GUILayout.Toggle(Plugin.Instance.SpeakerDistances.Value, "Show distance in metres", _toggleStyle, (Il2CppReferenceArray)null); if (flag4 != Plugin.Instance.SpeakerDistances.Value) { Plugin.Instance.SpeakerDistances.Value = flag4; } GUILayout.BeginHorizontal((Il2CppReferenceArray)null); GUILayout.Label("HUD size", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(85f) }); float num4 = GUILayout.HorizontalSlider(Plugin.Instance.HudScale.Value, 0.75f, 1.5f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(350f) }); GUILayout.Label($"{num4:0.00}×", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(65f) }); GUILayout.EndHorizontal(); if (!Mathf.Approximately(num4, Plugin.Instance.HudScale.Value)) { Plugin.Instance.HudScale.Value = num4; } float num5 = Mathf.Clamp(Plugin.Instance.TalkThreshold.Value, 0.0005f, 0.02f); float num6 = 1f - Mathf.Log(num5 / 0.0005f) / Mathf.Log(39.999996f); GUILayout.BeginHorizontal((Il2CppReferenceArray)null); GUILayout.Label("Sensitivity", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(85f) }); float num7 = GUILayout.HorizontalSlider(num6, 0f, 1f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(350f) }); GUILayout.Label(SensitivityLabel(num7), _mutedLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(65f) }); GUILayout.EndHorizontal(); if (!Mathf.Approximately(num7, num6)) { Plugin.Instance.TalkThreshold.Value = 0.0005f * Mathf.Pow(39.999996f, 1f - num7); } GUILayout.Label("Quick controls", _headingStyle, (Il2CppReferenceArray)null); GUILayout.Label("Click a binding, then press the new shortcut. Escape cancels; Delete clears.", _mutedLabelStyle, (Il2CppReferenceArray)null); DrawShortcutRow(ShortcutSlot.Menu); DrawShortcutRow(ShortcutSlot.AudioMode); DrawShortcutRow(ShortcutSlot.Range); DrawShortcutRow(ShortcutSlot.Hud); string text = FindShortcutConflict(); if (text != null) { GUILayout.Label("⚠ " + text, _labelStyle, (Il2CppReferenceArray)null); } else { GUILayout.Label("Optional shortcuts are unbound by default to avoid mod conflicts.", _mutedLabelStyle, (Il2CppReferenceArray)null); } GUILayout.Space(10f); DrawTalkers(); GUILayout.EndScrollView(); GUILayout.Space(5f); GUILayout.BeginHorizontal((Il2CppReferenceArray)null); GUILayout.Label(_status, _labelStyle, (Il2CppReferenceArray)null); if (GUILayout.Button("Reset", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) })) { ResetDefaults(); } if (GUILayout.Button("Close", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) })) { SetVisible(visible: false); } GUILayout.EndHorizontal(); GUI.color = color; GUI.DragWindow(); } private void DrawTalkers() { List controls = PlayerVoicePlaybackControl.controls; if (controls == null || controls.Count == 0) { GUILayout.Label("Players", _headingStyle, (Il2CppReferenceArray)null); GUILayout.Label("No remote voice players yet.", _labelStyle, (Il2CppReferenceArray)null); return; } GUILayout.Label($"Players ({controls.Count})", _headingStyle, (Il2CppReferenceArray)null); int num = 0; Enumerator enumerator = controls.GetEnumerator(); while (enumerator.MoveNext()) { PlayerVoicePlaybackControl current = enumerator.Current; if (!((Object)(object)current == (Object)null)) { num++; string text = PlayerVoiceInfo.DisplayName(current, num); bool flag = SpeakerIndicators.IsTalking(current); float num2 = PlayerVoiceInfo.DistanceFromCamera(current); string text2 = ((num2 >= 0f) ? $"{num2:0} m" : "—"); GUILayout.BeginHorizontal((Il2CppReferenceArray)null); GUILayout.Label(flag ? "● TALKING" : "○ quiet", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) }); GUILayout.Label(text, _labelStyle, (Il2CppReferenceArray)null); GUILayout.Label(text2, _mutedLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }); GUILayout.EndHorizontal(); } } } private void EnsureStyles() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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_00c7: Expected O, but got Unknown //IL_00cd: 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_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected O, but got Unknown //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown //IL_0148: 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_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0166: 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_017c: Expected O, but got Unknown //IL_0181: Expected O, but got Unknown //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Expected O, but got Unknown //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Expected O, but got Unknown //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Expected O, but got Unknown //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Expected O, but got Unknown //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_029f: 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_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Expected O, but got Unknown //IL_02b7: Expected O, but got Unknown if (_labelStyle == null) { _panelTexture = new Texture2D(1, 1, (TextureFormat)4, false); _panelTexture.SetPixel(0, 0, new Color(0.055f, 0.065f, 0.075f, 0.97f)); _panelTexture.Apply(); ((Object)_panelTexture).hideFlags = (HideFlags)61; _accentTexture = new Texture2D(1, 1, (TextureFormat)4, false); _accentTexture.SetPixel(0, 0, new Color(0.12f, 0.42f, 0.27f, 1f)); _accentTexture.Apply(); ((Object)_accentTexture).hideFlags = (HideFlags)61; _windowStyle = new GUIStyle(GUI.skin.window) { fontSize = 17, fontStyle = (FontStyle)1 }; SetTextColour(_windowStyle, Color.white); _labelStyle = new GUIStyle(GUI.skin.label) { fontSize = 16, wordWrap = true }; SetTextColour(_labelStyle, new Color(0.93f, 0.95f, 0.97f)); _mutedLabelStyle = new GUIStyle(_labelStyle) { fontSize = 14 }; SetTextColour(_mutedLabelStyle, new Color(0.67f, 0.72f, 0.76f)); _headingStyle = new GUIStyle(_labelStyle) { fontSize = 18, fontStyle = (FontStyle)1, margin = new RectOffset(4, 4, 8, 3) }; _buttonStyle = new GUIStyle(GUI.skin.button) { fontSize = 15, fixedHeight = 0f }; SetTextColour(_buttonStyle, Color.white); _selectedButtonStyle = new GUIStyle(_buttonStyle); _selectedButtonStyle.normal.background = _accentTexture; _selectedButtonStyle.hover.background = _accentTexture; _selectedButtonStyle.active.background = _accentTexture; SetTextColour(_selectedButtonStyle, Color.white); _toggleStyle = new GUIStyle(GUI.skin.toggle) { fontSize = 16, fixedHeight = 28f }; SetTextColour(_toggleStyle, Color.white); _textFieldStyle = new GUIStyle(GUI.skin.textField) { fontSize = 16, fixedHeight = 28f }; SetTextColour(_textFieldStyle, Color.white); _toastTitleStyle = new GUIStyle(_headingStyle) { alignment = (TextAnchor)3, fontSize = 16, margin = new RectOffset() }; } } private static void SetTextColour(GUIStyle style, Color colour) { //IL_0006: 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_001e: 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_0036: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) style.normal.textColor = colour; style.hover.textColor = colour; style.active.textColor = colour; style.focused.textColor = colour; style.onNormal.textColor = colour; style.onHover.textColor = colour; style.onActive.textColor = colour; style.onFocused.textColor = colour; } private bool PresetButton(string label, float value) { bool flag = Mathf.Abs(VoiceRangeScaler.Scale - value) < 0.01f; return GUILayout.Button($"{label}\n×{value:0}", flag ? _selectedButtonStyle : _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(46f) }); } private static string SensitivityLabel(float value) { if (value < 0.25f) { return "Low"; } if (value < 0.7f) { return "Normal"; } return "High"; } private static string ShortcutName(string shortcut) { return ShortcutBinding.Display(shortcut); } private void DrawShortcutRow(ShortcutSlot slot) { string text = ShortcutActionName(slot); ConfigEntry val = ShortcutEntry(slot); bool flag = _capturingShortcut == slot; GUILayout.BeginHorizontal((Il2CppReferenceArray)null); GUILayout.Label(text, _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) }); if (GUILayout.Button(flag ? "Press a shortcut…" : ShortcutName(val.Value), flag ? _selectedButtonStyle : _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { _capturingShortcut = slot; GUI.FocusControl((string)null); _status = "Listening for " + text.ToLowerInvariant() + " shortcut…"; } if (GUILayout.Button("Clear", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(65f), GUILayout.Height(30f) })) { val.Value = "Not bound"; if (flag) { _capturingShortcut = ShortcutSlot.None; } _status = text + " shortcut cleared."; } GUILayout.EndHorizontal(); } private void HandleShortcutCapture(Event currentEvent) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Invalid comparison between Unknown and I4 //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Invalid comparison between Unknown and I4 //IL_0082: 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) if (_capturingShortcut == ShortcutSlot.None || currentEvent == null || (int)currentEvent.type != 4) { return; } KeyCode keyCode = currentEvent.keyCode; if (IsModifier(keyCode)) { return; } if ((int)keyCode == 27) { _status = "Shortcut change cancelled."; _capturingShortcut = ShortcutSlot.None; currentEvent.Use(); return; } ConfigEntry val = ShortcutEntry(_capturingShortcut); string text = ShortcutActionName(_capturingShortcut); if ((int)keyCode == 127 || (int)keyCode == 8) { val.Value = "Not bound"; _status = text + " shortcut cleared."; } else { if ((int)keyCode == 0) { return; } string shortcut = (val.Value = ShortcutFromEvent(currentEvent, keyCode)); _status = text + ": " + ShortcutName(shortcut); } _capturingShortcut = ShortcutSlot.None; currentEvent.Use(); } private unsafe static string ShortcutFromEvent(Event currentEvent, KeyCode mainKey) { List list = new List(); if (currentEvent.control) { list.Add("LeftControl"); } if (currentEvent.shift) { list.Add("LeftShift"); } if (currentEvent.alt) { list.Add("LeftAlt"); } if (currentEvent.command) { list.Add("LeftCommand"); } list.Add(((object)(*(KeyCode*)(&mainKey))/*cast due to .constrained prefix*/).ToString()); return string.Join(" + ", list); } private static bool IsModifier(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 if ((int)key != 308 && (int)key != 307 && (int)key != 306 && (int)key != 305 && (int)key != 304 && (int)key != 303 && (int)key != 310 && (int)key != 309 && (int)key != 311) { return (int)key == 312; } return true; } private static ConfigEntry ShortcutEntry(ShortcutSlot slot) { return (ConfigEntry)(slot switch { ShortcutSlot.Menu => Plugin.Instance.MenuShortcut, ShortcutSlot.AudioMode => Plugin.Instance.ToggleTwoDShortcut, ShortcutSlot.Range => Plugin.Instance.CycleRangeShortcut, ShortcutSlot.Hud => Plugin.Instance.ToggleHudShortcut, _ => throw new ArgumentOutOfRangeException("slot"), }); } private static string ShortcutActionName(ShortcutSlot slot) { return slot switch { ShortcutSlot.Menu => "Open menu", ShortcutSlot.AudioMode => "2D / 3D", ShortcutSlot.Range => "Cycle range", ShortcutSlot.Hud => "Toggle HUD", _ => "Shortcut", }; } private static string FindShortcutConflict() { (string, string)[] array = new(string, string)[4] { ("Menu", Plugin.Instance.MenuShortcut.Value), ("2D/3D", Plugin.Instance.ToggleTwoDShortcut.Value), ("Cycle range", Plugin.Instance.CycleRangeShortcut.Value), ("HUD", Plugin.Instance.ToggleHudShortcut.Value) }; for (int i = 0; i < array.Length; i++) { if (!ShortcutBinding.IsBound(array[i].Item2)) { continue; } for (int j = i + 1; j < array.Length; j++) { if (ShortcutBinding.IsBound(array[j].Item2) && ShortcutBinding.Equivalent(array[i].Item2, array[j].Item2)) { return array[i].Item1 + " and " + array[j].Item1 + " use the same shortcut."; } } } (string, string)[] array2 = array; for (int k = 0; k < array2.Length; k++) { (string, string) tuple = array2[k]; if (!ShortcutBinding.IsValid(tuple.Item2)) { return tuple.Item1 + " has an invalid shortcut: '" + tuple.Item2 + "'."; } } return null; } private string EffectiveRangeDescription() { List controls = PlayerVoicePlaybackControl.controls; if (Plugin.Instance.TwoDVoice.Value) { return "2D mode bypasses positional distance fade."; } if (controls == null) { return "Effective distance appears after another player joins."; } Enumerator enumerator = controls.GetEnumerator(); while (enumerator.MoveNext()) { PlayerVoicePlaybackControl current = enumerator.Current; if (!((Object)(object)current == (Object)null)) { float num = PlayerVoiceInfo.AudibleRange(current); if (num > 0f) { return $"Current received-voice edge: approximately {num:0} metres."; } } } return "Effective distance appears after another player speaks."; } private void SetRange(float value, bool notify = false) { float num = Mathf.Clamp(value, 1f, 20f); Plugin.Instance.RangeMultiplier.Value = num; _rangeText = num.ToString("0.##", CultureInfo.InvariantCulture); ApplySettings(); if (notify) { ShowToast($"VOICE RANGE ×{num:0.##}", RangePresetDescription(num)); } } private void SetTwoD(bool enabled, bool notify) { Plugin.Instance.TwoDVoice.Value = enabled; ApplySettings(); if (notify) { ShowToast(enabled ? "2D VOICE" : "3D SPATIAL VOICE", enabled ? "Voices are centred with no distance fade." : "Direction and distance are restored."); } } private void CycleRange() { float value = Plugin.Instance.RangeMultiplier.Value; float value2 = RangePresets[0]; float[] rangePresets = RangePresets; foreach (float num in rangePresets) { if (num > value + 0.01f) { value2 = num; break; } } SetRange(value2, notify: true); } private static string RangePresetDescription(float range) { if (range <= 1.01f) { return "Vanilla received-voice distance."; } if (range <= 2.01f) { return "A comfortable social boost."; } if (range <= 5.01f) { return "Wide-area conversation."; } if (range <= 10.01f) { return "Far-reaching conversation."; } return "Maximum received-voice distance."; } private void ShowToast(string title, string detail) { _toastTitle = title; _toastDetail = detail; _toastUntil = Time.unscaledTime + 2.6f; } private void ResetDefaults() { Plugin.Instance.RangeMultiplier.Value = 1f; Plugin.Instance.TwoDVoice.Value = false; Plugin.Instance.SpeakerIndicators.Value = true; Plugin.Instance.SpeakerNames.Value = true; Plugin.Instance.ActiveSpeakerRoster.Value = true; Plugin.Instance.SpeakerDistances.Value = true; Plugin.Instance.HudScale.Value = 1f; Plugin.Instance.TalkThreshold.Value = 0.004f; _rangeText = "1"; ApplySettings(); ShowToast("VOICE SETTINGS RESET", "Vanilla range, 3D audio, and the full speaker HUD."); } private void DrawToast() { //IL_0045: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_00d8: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Min(460f, (float)Screen.width - 32f); float num2 = 72f; float num3 = ((float)Screen.width - num) * 0.5f; float num4 = 26f; GUI.color = new Color(0.025f, 0.03f, 0.035f, 0.94f); GUI.DrawTexture(new Rect(num3, num4, num, num2), (Texture)(object)_panelTexture); GUI.color = Color.white; GUI.DrawTexture(new Rect(num3, num4, 5f, num2), (Texture)(object)_accentTexture); GUI.color = Color.white; GUI.Label(new Rect(num3 + 18f, num4 + 8f, num - 30f, 26f), _toastTitle, _toastTitleStyle); GUI.Label(new Rect(num3 + 18f, num4 + 34f, num - 30f, 25f), _toastDetail, _mutedLabelStyle); } private void ApplySettings() { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown try { float value = (VoiceRangeScaler.Scale = Mathf.Clamp(Plugin.Instance.RangeMultiplier.Value, 1f, 20f)); VoiceRangeScaler.Apply(); List controls = PlayerVoicePlaybackControl.controls; if (controls != null) { Enumerator enumerator = controls.GetEnumerator(); while (enumerator.MoveNext()) { PlayerVoicePlaybackControl current = enumerator.Current; if ((Object)(object)current != (Object)null) { current.TwoDMode = Plugin.Instance.TwoDVoice.Value; } } } _status = ((VoiceRangeScaler.LastApplied == 0) ? "Waiting for remote players…" : $"Applied ×{value:0.##} to {VoiceRangeScaler.LastApplied} player(s)."); } catch (Exception ex) { _status = "Could not apply voice settings; check the BepInEx log."; ManualLogSource trace = Plugin.Trace; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(32, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Applying voice settings failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex); } trace.LogError(val); } } private void SetVisible(bool visible) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (_visible == visible) { return; } _visible = visible; if (!Plugin.Instance.FreeCursor.Value) { return; } if (visible) { _previousLockState = Cursor.lockState; _previousCursorVisible = Cursor.visible; return; } Cursor.lockState = _previousLockState; Cursor.visible = _previousCursorVisible; SettingsMenu returnToSettingsMenu = _returnToSettingsMenu; _returnToSettingsMenu = null; if ((Object)(object)returnToSettingsMenu != (Object)null) { ((Component)returnToSettingsMenu).gameObject.SetActive(true); returnToSettingsMenu.SetToAudio(); NativeSettingsIntegration.Refresh(); } } internal void ApplyImmediately() { ApplySettings(); } internal void OpenFromNativeSettings(SettingsMenu settingsMenu) { _returnToSettingsMenu = settingsMenu; if (settingsMenu != null) { ((Component)settingsMenu).gameObject.SetActive(false); } SetVisible(visible: true); } } }