using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using MenuLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.Layouts; using UnityEngine.InputSystem.LowLevel; using UnityEngine.SceneManagement; using UnityEngine.UI; [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("NativeController")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.6.0.0")] [assembly: AssemblyInformationalVersion("0.6.0+2074cbac6ea40b26f02c830fd79b13635a80bf22")] [assembly: AssemblyProduct("NativeController")] [assembly: AssemblyTitle("NativeController")] [assembly: AssemblyVersion("0.6.0.0")] [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 NativeController { internal class AimAssist : MonoBehaviour { internal static bool HasTarget; internal static Vector3 TargetPosition; private const float CastRadius = 0.4f; private const float LosMargin = 0.5f; private const float AcquireFraction = 0.6f; private const float SwitchMarginDeg = 4f; private const float MinDwellSeconds = 0.15f; private const float PointSmoothTime = 0.08f; private static readonly FieldRef GrabbedRef = AccessTools.FieldRefAccess("grabbedPhysGrabObject"); private static readonly FieldRef EnemyRef = AccessTools.FieldRefAccess("Enemy"); private static readonly FieldRef SpawnedRef = AccessTools.FieldRefAccess("Spawned"); private int _itemMask; private int _losMask; private bool _masksReady; private GameObject _lastTarget; private float _dwellTimer; private Vector3 _smoothedPoint; private Vector3 _pointVel; private void Update() { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_00ad: 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_0093: 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_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0130: 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) if (!Plugin.Enabled.Value || !Plugin.AimAssistEnabled.Value) { Forget(); return; } CameraAim instance = CameraAim.Instance; Camera main = Camera.main; if ((Object)(object)instance == (Object)null || (Object)(object)main == (Object)null) { Forget(); return; } EnsureMasks(); if (_dwellTimer > 0f) { _dwellTimer -= Time.deltaTime; } Vector3 position = ((Component)main).transform.position; Vector3 forward = ((Component)main).transform.forward; if ((!Plugin.AimAssistEnemies.Value || !IsArmed() || !TryFindEnemy(position, forward, out var pos, out var go)) && (!Plugin.AimAssistItems.Value || !TryFindItem(position, forward, out pos, out go))) { Forget(); return; } if ((Object)(object)go != (Object)(object)_lastTarget) { _lastTarget = go; _smoothedPoint = pos; _pointVel = Vector3.zero; _dwellTimer = 0.15f; Plugin.Log.LogDebug((object)("[AimAssist] target -> " + ((Object)go).name)); } else { _smoothedPoint = Vector3.SmoothDamp(_smoothedPoint, pos, ref _pointVel, 0.08f); } TargetPosition = _smoothedPoint; HasTarget = true; } private void OnDisable() { Forget(); } private void Forget() { HasTarget = false; if ((Object)(object)_lastTarget != (Object)null) { _lastTarget = null; Plugin.Log.LogDebug((object)"[AimAssist] target -> none"); } } private static bool IsArmed() { PhysGrabber instance = PhysGrabber.instance; if ((Object)(object)instance == (Object)null) { return false; } PhysGrabObject val = GrabbedRef.Invoke(instance); if ((Object)(object)val == (Object)null) { return false; } GameObject gameObject = ((Component)val).gameObject; if (!((Object)(object)gameObject.GetComponentInChildren() != (Object)null) && !((Object)(object)gameObject.GetComponentInChildren() != (Object)null)) { return (Object)(object)gameObject.GetComponentInChildren() != (Object)null; } return true; } private bool TryFindEnemy(Vector3 origin, Vector3 fwd, out Vector3 pos, out GameObject go) { //IL_0001: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) pos = Vector3.zero; go = null; EnemyDirector instance = EnemyDirector.instance; if ((Object)(object)instance == (Object)null || instance.enemiesSpawned == null) { return false; } float value = Plugin.AimAssistMaxAngle.Value; float num = value * 0.6f; float value2 = Plugin.AimAssistEnemyRange.Value; GameObject bestGo = null; float num2 = value; Vector3 bestPos = Vector3.zero; GameObject curGo = null; float curAngle = value; Vector3 curPos = Vector3.zero; foreach (EnemyParent item in instance.enemiesSpawned) { if ((Object)(object)item == (Object)null || !SpawnedRef.Invoke(item)) { continue; } Enemy val = EnemyRef.Invoke(item); if ((Object)(object)val == (Object)null) { continue; } Transform val2 = (((Object)(object)val.CenterTransform != (Object)null) ? val.CenterTransform : ((Component)val).transform); GameObject gameObject = ((Component)val).gameObject; float maxAngle = (((Object)(object)gameObject == (Object)(object)_lastTarget) ? value : num); if (Passes(origin, fwd, val2.position, value2, maxAngle, out var angle)) { if ((Object)(object)gameObject == (Object)(object)_lastTarget) { curGo = gameObject; curAngle = angle; curPos = val2.position; } if (angle < num2) { num2 = angle; bestGo = gameObject; bestPos = val2.position; } } } return Resolve(bestGo, num2, bestPos, curGo, curAngle, curPos, out pos, out go); } private bool TryFindItem(Vector3 origin, Vector3 fwd, out Vector3 pos, out GameObject go) { //IL_0001: 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_002d: 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_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_0053: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0119: 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_00aa: 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_00c3: 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_00e9: 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_00fa: 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) pos = Vector3.zero; go = null; float value = Plugin.AimAssistMaxAngle.Value; float num = value * 0.6f; float value2 = Plugin.AimAssistItemRange.Value; RaycastHit[] array = Physics.SphereCastAll(origin, 0.4f, fwd, value2, _itemMask, (QueryTriggerInteraction)2); GameObject bestGo = null; float num2 = value; Vector3 bestPos = Vector3.zero; GameObject curGo = null; float curAngle = value; Vector3 curPos = Vector3.zero; RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val = array2[i]; if (!((Component)((RaycastHit)(ref val)).collider).CompareTag("Phys Grab Object")) { continue; } PhysGrabObject componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent(); if ((Object)(object)componentInParent == (Object)null) { continue; } GameObject gameObject = ((Component)componentInParent).gameObject; Vector3 centerPoint = componentInParent.centerPoint; float maxAngle = (((Object)(object)gameObject == (Object)(object)_lastTarget) ? value : num); if (Passes(origin, fwd, centerPoint, value2, maxAngle, out var angle)) { if ((Object)(object)gameObject == (Object)(object)_lastTarget) { curGo = gameObject; curAngle = angle; curPos = centerPoint; } if (angle < num2) { num2 = angle; bestGo = gameObject; bestPos = centerPoint; } } } return Resolve(bestGo, num2, bestPos, curGo, curAngle, curPos, out pos, out go); } private bool Resolve(GameObject bestGo, float bestAngle, Vector3 bestPos, GameObject curGo, float curAngle, Vector3 curPos, out Vector3 pos, out GameObject go) { //IL_003e: 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_002e: 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) if ((Object)(object)curGo != (Object)null && ((Object)(object)bestGo == (Object)(object)curGo || _dwellTimer > 0f || bestAngle > curAngle - 4f)) { pos = curPos; go = curGo; return true; } pos = bestPos; go = bestGo; return (Object)(object)go != (Object)null; } private bool Passes(Vector3 origin, Vector3 fwd, Vector3 target, float range, float maxAngle, out float angle) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_003a: 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_003d: Unknown result type (might be due to invalid IL or missing references) angle = 999f; Vector3 val = target - origin; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.05f || magnitude > range) { return false; } angle = Vector3.Angle(fwd, val); if (angle > maxAngle) { return false; } if (Physics.Raycast(origin, val / magnitude, magnitude - 0.5f, _losMask)) { return false; } return true; } private void EnsureMasks() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (!_masksReady) { _itemMask = (_losMask = LayerMask.op_Implicit(SemiFunc.LayerMaskGetVisionObstruct())) & ~LayerMask.GetMask(new string[1] { "Player" }); _masksReady = true; } } } internal static class ButtonNames { internal enum Control { South, East, West, North, LB, RB, LT, RT, L3, R3, DpadLeft, DpadUp, DpadRight, DpadDown, Start, Select, LStick, RStick } internal static string Of(Control c, ControllerDetect.Kind kind) { return kind switch { ControllerDetect.Kind.PlayStation => Ps(c), ControllerDetect.Kind.Switch => Sw(c), _ => Xbox(c), }; } private static string Xbox(Control c) { return c switch { Control.South => "A", Control.East => "B", Control.West => "X", Control.North => "Y", Control.LB => "LB", Control.RB => "RB", Control.LT => "LT", Control.RT => "RT", Control.L3 => "L3", Control.R3 => "R3", Control.DpadLeft => "←", Control.DpadUp => "↑", Control.DpadRight => "→", Control.DpadDown => "↓", Control.Start => "Menu", Control.Select => "View", Control.LStick => "L-Stick", Control.RStick => "R-Stick", _ => "?", }; } private static string Ps(Control c) { return c switch { Control.South => "✕", Control.East => "○", Control.West => "□", Control.North => "△", Control.LB => "L1", Control.RB => "R1", Control.LT => "L2", Control.RT => "R2", Control.L3 => "L3", Control.R3 => "R3", Control.DpadLeft => "←", Control.DpadUp => "↑", Control.DpadRight => "→", Control.DpadDown => "↓", Control.Start => "Options", Control.Select => "Create", Control.LStick => "L-Stick", Control.RStick => "R-Stick", _ => "?", }; } private static string Sw(Control c) { return c switch { Control.South => "B", Control.East => "A", Control.West => "Y", Control.North => "X", Control.LB => "L", Control.RB => "R", Control.LT => "ZL", Control.RT => "ZR", Control.L3 => "L3", Control.R3 => "R3", Control.DpadLeft => "←", Control.DpadUp => "↑", Control.DpadRight => "→", Control.DpadDown => "↓", Control.Start => "+", Control.Select => "-", Control.LStick => "L-Stick", Control.RStick => "R-Stick", _ => "?", }; } } internal class ChatKeyboard : MonoBehaviour { private static readonly FieldRef ChatActiveRef = AccessTools.FieldRefAccess("chatActive"); private static readonly FieldRef ChatMessageRef = AccessTools.FieldRefAccess("chatMessage"); private static readonly FieldRef> ChatHistoryRef = AccessTools.FieldRefAccess>("chatHistory"); private static readonly FieldRef ChatHistoryIndexRef = AccessTools.FieldRefAccess("chatHistoryIndex"); private static readonly Action StateSet = AccessTools.MethodDelegate>(AccessTools.Method(typeof(ChatManager), "StateSet", (Type[])null, (Type[])null), (object)null, true); internal static bool Open; internal static float PanelTop; private const int MaxChatLength = 50; private const float PadOpenWindow = 0.25f; private const float FlickFire = 0.6f; private const float FlickRearm = 0.3f; private readonly PadKeyboardCore _core = new PadKeyboardCore(hasSpace: true, "SEND", "CLOSE"); private bool _selectArmed; private float _lastSelectPress = -10f; private bool _prevChatActive; private bool _flickArmed; private static bool _warned; private void Awake() { _core.OnChar = TypeChar; _core.OnConfirm = SendOrClose; _core.OnClose = Cancel; } internal static void ResetState() { Open = false; PanelTop = 0f; } private void Update() { ChatManager instance = ChatManager.instance; Gamepad current = Gamepad.current; if ((Object)(object)instance == (Object)null || !Plugin.Enabled.Value || !Plugin.ChatKeyboardEnabled.Value) { Open = false; return; } bool flag; try { flag = ChatActiveRef.Invoke(instance); } catch (Exception e) { WarnOnce(e); Open = false; return; } if (current != null && current.selectButton.wasPressedThisFrame) { _lastSelectPress = Time.unscaledTime; } if (!flag) { Open = false; _prevChatActive = false; return; } if (!_prevChatActive) { _prevChatActive = true; if (current != null && Time.unscaledTime - _lastSelectPress < 0.25f) { Open = true; PanelTop = 0f; _core.Reset(); _selectArmed = false; _flickArmed = false; } } if (!Open || current == null) { return; } if (!current.selectButton.isPressed && !current.selectButton.wasReleasedThisFrame) { _selectArmed = true; } try { _core.HandleInput(current); HandleHistoryFlick(current, instance); if (_selectArmed && current.selectButton.wasReleasedThisFrame) { Cancel(); } } catch (Exception e2) { WarnOnce(e2); } } private void TypeChar(string s) { //IL_0098: 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) ChatManager instance = ChatManager.instance; if (!((Object)(object)instance == (Object)null)) { if ((ChatMessageRef.Invoke(instance) ?? "").Length >= 50) { ((SemiUI)ChatUI.instance).SemiUITextFlashColor(Color.red, 0.2f); ((SemiUI)ChatUI.instance).SemiUISpringShakeX(10f, 10f, 0.3f); ((SemiUI)ChatUI.instance).SemiUISpringScale(0.05f, 5f, 0.2f); MenuManager.instance.MenuEffectClick((MenuClickEffectType)2, (MenuPage)null, 1f, 1f, true); } else { instance.AddLetterToChat(s); ((SemiUI)ChatUI.instance).SemiUITextFlashColor(Color.yellow, 0.2f); ((SemiUI)ChatUI.instance).SemiUISpringShakeY(2f, 5f, 0.2f); MenuManager.instance.MenuEffectClick((MenuClickEffectType)4, (MenuPage)null, 2f, 0.2f, true); } } } private void HandleHistoryFlick(Gamepad gp, ChatManager chat) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (chat.StateIsActive() && Plugin.ChatHistoryRecallEnabled.Value) { float y = ((InputControl)(object)gp.rightStick).ReadValue().y; if (Mathf.Abs(y) < Mathf.Max(0.3f, Plugin.StickDeadzone.Value)) { _flickArmed = true; } else if (_flickArmed && !(Mathf.Abs(y) < 0.6f)) { _flickArmed = false; HistoryStep(chat, y > 0f); } } } private void HistoryStep(ChatManager chat, bool older) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) List list = ChatHistoryRef.Invoke(chat); if (list == null || list.Count == 0) { return; } ref int reference = ref ChatHistoryIndexRef.Invoke(chat); if (older) { if (reference > 0) { reference--; } else { reference = list.Count - 1; } } else if (reference < list.Count - 1) { reference++; } else { reference = 0; } string text = list[reference]; ChatMessageRef.Invoke(chat) = text; ((TMP_Text)chat.chatText).text = text; ((SemiUI)ChatUI.instance).SemiUITextFlashColor(Color.cyan, 0.2f); ((SemiUI)ChatUI.instance).SemiUISpringShakeY(2f, 5f, 0.2f); MenuManager.instance.MenuEffectClick((MenuClickEffectType)4, (MenuPage)null, 1f, 0.2f, true); } private void SendOrClose() { ChatManager instance = ChatManager.instance; if (!((Object)(object)instance == (Object)null)) { if ((ChatMessageRef.Invoke(instance) ?? "") != "") { instance.ForceConfirmChat(); return; } StateSet(instance, (ChatState)0); Open = false; } } private void Cancel() { ChatManager instance = ChatManager.instance; if (!((Object)(object)instance == (Object)null)) { StateSet(instance, (ChatState)0); ((SemiUI)ChatUI.instance).SemiUISpringShakeX(10f, 10f, 0.3f); ((SemiUI)ChatUI.instance).SemiUISpringScale(0.05f, 5f, 0.2f); MenuManager.instance.MenuEffectClick((MenuClickEffectType)2, (MenuPage)null, 1f, 1f, true); Open = false; } } private static void WarnOnce(Exception e) { if (!_warned) { _warned = true; Plugin.Log.LogWarning((object)("[ChatKeyboard] Error (further warnings suppressed): " + e.Message)); } } private void OnGUI() { if (Open) { float value = Plugin.ChatScale.Value; _core.Draw(value, Mathf.Max(40f * value, (float)Screen.height * 0.13f)); PanelTop = _core.LastPanelTop; } } } [HarmonyPatch] internal static class ChatKeyboardMapGuard { [HarmonyPatch(typeof(InputManager), "KeyDown")] [HarmonyPostfix] private static void KeyDownPostfix(InputKey key, ref bool __result) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if (__result && (int)key == 8 && ChatKeyboard.Open) { __result = false; } } [HarmonyPatch(typeof(InputManager), "KeyHold")] [HarmonyPostfix] private static void KeyHoldPostfix(InputKey key, ref bool __result) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if (__result && (int)key == 8 && ChatKeyboard.Open) { __result = false; } } } internal class ChatLog : MonoBehaviour { private struct Entry { public string Name; public string Text; } private const int MaxEntries = 30; private const float FadeSeconds = 1f; private static readonly List Entries = new List(); private static float _lastMessageTime = -1000f; private static int _entriesVersion; private GUIStyle _line; private GUIStyle _name; private float _styleScale = -1f; private int _layoutVersion = -1; private int _layoutCount; private float _layoutScale = -1f; private float _panelW; private float _layoutScreenW = -1f; private float[] _nameWidths; internal static void Append(string name, string text) { Entries.Add(new Entry { Name = (string.IsNullOrEmpty(name) ? "???" : name) + ":", Text = " " + text }); if (Entries.Count > 30) { Entries.RemoveAt(0); } _lastMessageTime = Time.unscaledTime; _entriesVersion++; } private void OnGUI() { //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Expected O, but got Unknown //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Expected O, but got Unknown //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_021e: 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_0283: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: 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_0329: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.Enabled.Value || !Plugin.ChatLogEnabled.Value || Entries.Count == 0) { return; } float num = VisibleAlpha(); if (num <= 0f) { return; } float num2 = Plugin.ChatScale.Value * 2.142857f; EnsureStyles(num2); int num3 = Mathf.Min(Plugin.ChatLogMaxVisible.Value, Entries.Count); float num4 = 20f * num2; float num5 = 8f * num2; float num6 = 5f * num2; float num7 = 12f * num2; if (_layoutVersion != _entriesVersion || !Mathf.Approximately(_layoutScale, num2) || _layoutCount != num3 || !Mathf.Approximately(_layoutScreenW, (float)Screen.width)) { _layoutVersion = _entriesVersion; _layoutScale = num2; _layoutCount = num3; _layoutScreenW = Screen.width; if (_nameWidths == null || _nameWidths.Length < num3) { _nameWidths = new float[num3]; } _panelW = 0f; for (int i = 0; i < num3; i++) { Entry entry = Entries[Entries.Count - num3 + i]; float x = _name.CalcSize(new GUIContent(entry.Name)).x; float x2 = _line.CalcSize(new GUIContent(entry.Text)).x; _nameWidths[i] = x; _panelW = Mathf.Max(_panelW, x + x2); } _panelW = Mathf.Min(_panelW + 2f * num5, (float)Screen.width - 2f * num7); } float num8 = (float)num3 * num4 + 2f * num6; float num9 = (float)Screen.height - num7; if (ChatKeyboard.Open && ChatKeyboard.PanelTop > 0f) { num9 = ChatKeyboard.PanelTop - num7; } float num10 = num7; float num11 = num9 - num8; GUI.color = new Color(0f, 0f, 0f, 0.55f * num); GUI.DrawTexture(new Rect(num10, num11, _panelW, num8), (Texture)(object)Texture2D.whiteTexture); for (int j = 0; j < num3; j++) { Entry entry2 = Entries[Entries.Count - num3 + j]; float num12 = num11 + num6 + (float)j * num4; GUI.color = new Color(1f, 0.85f, 0.3f, num); GUI.Label(new Rect(num10 + num5, num12, _nameWidths[j], num4), entry2.Name, _name); GUI.color = new Color(1f, 1f, 1f, num); GUI.Label(new Rect(num10 + num5 + _nameWidths[j], num12, Mathf.Max(0f, _panelW - 2f * num5 - _nameWidths[j]), num4), entry2.Text, _line); } GUI.color = Color.white; } private static float VisibleAlpha() { ChatManager instance = ChatManager.instance; if ((Object)(object)instance != (Object)null && !instance.StateIsInactive()) { return 1f; } float value = Plugin.ChatLogVisibleSeconds.Value; if (value <= 0f) { return 0f; } float num = value - (Time.unscaledTime - _lastMessageTime); if (num <= 0f) { return 0f; } if (!(num >= 1f)) { return num / 1f; } return 1f; } private void EnsureStyles(float scale) { //IL_0029: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0053: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown if (_line == null || !Mathf.Approximately(_styleScale, scale)) { _styleScale = scale; _line = new GUIStyle(GUI.skin.label) { fontSize = (int)(14f * scale), alignment = (TextAnchor)3 }; _line.normal.textColor = Color.white; _name = new GUIStyle(_line) { fontStyle = (FontStyle)1 }; _layoutScale = -1f; } } } [HarmonyPatch] internal static class ChatLogCapturePatch { private static readonly FieldRef PlayerNameRef; private static bool _warned; static ChatLogCapturePatch() { try { PlayerNameRef = AccessTools.FieldRefAccess("playerName"); } catch { PlayerNameRef = null; } } [HarmonyPatch(typeof(PlayerAvatar), "ChatMessageSpeak")] [HarmonyPostfix] private static void Postfix(PlayerAvatar __instance, string _message) { if (!Plugin.Enabled.Value || !Plugin.ChatLogEnabled.Value) { return; } try { if (PlayerNameRef == null) { WarnOnce("playerName field not found"); } else { ChatLog.Append(PlayerNameRef.Invoke(__instance), _message); } } catch (Exception ex) { WarnOnce(ex.Message); } } private static void WarnOnce(string why) { if (!_warned) { _warned = true; Plugin.Log.LogWarning((object)("[ChatLog] Capture disabled (further warnings suppressed): " + why)); } } } internal static class ControllerDetect { internal enum Kind { None, Xbox, PlayStation, Switch, Generic } internal enum Style { Auto, Xbox, PlayStation, Switch } private static Kind _detected; private static bool _padActiveInit; internal static Kind Current => ((Plugin.GlyphStyle != null) ? Plugin.GlyphStyle.Value : Style.Auto) switch { Style.Xbox => Kind.Xbox, Style.PlayStation => Kind.PlayStation, Style.Switch => Kind.Switch, _ => _detected, }; internal static bool PadActive { get; private set; } internal static bool PadTouchedThisLevel { get; private set; } internal static void ResetLevelTouch() { PadTouchedThisLevel = false; } internal static void TrackActiveInput() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_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_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) Gamepad current = Gamepad.current; if (current == null) { PadActive = false; _padActiveInit = true; return; } if (!_padActiveInit) { _padActiveInit = true; PadActive = true; } Vector2 val = ((InputControl)(object)current.leftStick).ReadValue(); if (!(((Vector2)(ref val)).sqrMagnitude > 0.02f)) { val = ((InputControl)(object)current.rightStick).ReadValue(); if (!(((Vector2)(ref val)).sqrMagnitude > 0.02f) && !(((InputControl)(object)current.dpad).ReadValue() != Vector2.zero) && !current.buttonSouth.isPressed && !current.buttonEast.isPressed && !current.buttonWest.isPressed && !current.buttonNorth.isPressed && !current.leftTrigger.isPressed && !current.rightTrigger.isPressed && !current.leftShoulder.isPressed && !current.rightShoulder.isPressed && !current.startButton.isPressed && !current.selectButton.isPressed && !current.leftStickButton.isPressed && !current.rightStickButton.isPressed) { Mouse current2 = Mouse.current; int num; if (current2 != null) { val = ((InputControl)(object)((Pointer)current2).delta).ReadValue(); num = ((((Vector2)(ref val)).sqrMagnitude > 4f || current2.leftButton.isPressed || current2.rightButton.isPressed) ? 1 : 0); } else { num = 0; } Keyboard current3 = Keyboard.current; bool flag = current3 != null && ((ButtonControl)current3.anyKey).isPressed; if (((uint)num | (flag ? 1u : 0u)) != 0) { PadActive = false; } return; } } PadActive = true; PadTouchedThisLevel = true; } internal static void Init() { Detect(); InputSystem.onDeviceChange += delegate(InputDevice device, InputDeviceChange change) { if (device is Gamepad) { Detect(); } }; } private static void Detect() { Gamepad current = Gamepad.current; Kind kind = Classify(current); if (kind != _detected) { _detected = kind; string arg = ((current == null) ? "none" : (((InputControl)current).displayName + " (layout=" + ((InputControl)current).layout + ")")); Style style = ((Plugin.GlyphStyle != null) ? Plugin.GlyphStyle.Value : Style.Auto); string arg2 = ((style == Style.Auto) ? "" : $" (glyph override active: {style})"); Plugin.Log.LogInfo((object)$"[Gamepad] Detected controller: {kind} — {arg}{arg2}"); } } private static Kind Classify(Gamepad gp) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (gp == null) { return Kind.None; } InputDeviceDescription description = ((InputDevice)gp).description; string text = (((InputDeviceDescription)(ref description)).manufacturer + " " + ((InputDeviceDescription)(ref description)).product + " " + ((InputControl)gp).layout + " " + ((InputControl)gp).name).ToLowerInvariant(); if (text.Contains("dualsense") || text.Contains("dualshock") || text.Contains("sony") || text.Contains("playstation") || text.Contains("wireless controller")) { return Kind.PlayStation; } if (text.Contains("switch") || text.Contains("pro controller") || text.Contains("nintendo") || text.Contains("joy-con")) { return Kind.Switch; } if (text.Contains("xinput") || text.Contains("xbox")) { return Kind.Xbox; } return Kind.Generic; } } internal static class ControllerGlyphs { private static Font _symbol; private static bool _tried; private static GUIStyle _shapeStyle; private static Font Symbol() { if (!_tried) { _tried = true; try { _symbol = Font.CreateDynamicFontFromOSFont(new string[4] { "Arial Unicode MS", "Segoe UI Symbol", "Segoe UI", "Arial" }, 16); } catch { _symbol = null; } } return _symbol; } private static bool IsSymbol(char c) { if (c != '○' && c != '□' && c != '△' && c != '←' && c != '↑' && c != '→') { return c == '↓'; } return true; } private static bool HasSymbol(string s) { for (int i = 0; i < s.Length; i++) { if (IsSymbol(s[i])) { return true; } } return false; } internal static void DrawLabel(Rect rect, string text, GUIStyle style) { //IL_0017: 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_0077: 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_0031: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_00ba: 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_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Expected O, but got Unknown //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) Font val = Symbol(); if ((Object)(object)val == (Object)null || !HasSymbol(text)) { GUI.Label(rect, text, style); return; } if (_shapeStyle == null) { _shapeStyle = new GUIStyle(); } _shapeStyle.font = val; _shapeStyle.fontSize = style.fontSize; _shapeStyle.fontStyle = style.fontStyle; _shapeStyle.alignment = (TextAnchor)0; _shapeStyle.normal.textColor = style.normal.textColor; float num = ((Rect)(ref rect)).x; int i = 0; while (i < text.Length) { if (IsSymbol(text[i])) { string text2 = text[i].ToString(); float x = _shapeStyle.CalcSize(new GUIContent(text2)).x; GUI.Label(new Rect(num, ((Rect)(ref rect)).y, x, ((Rect)(ref rect)).height), text2, _shapeStyle); num += x; i++; continue; } int num2 = i; for (; i < text.Length && !IsSymbol(text[i]); i++) { } string text3 = text.Substring(num2, i - num2); float x2 = style.CalcSize(new GUIContent(text3)).x; GUI.Label(new Rect(num, ((Rect)(ref rect)).y, x2, ((Rect)(ref rect)).height), text3, style); num += x2; } } } internal class ControllerLayoutOverlay : MonoBehaviour { private static readonly FieldRef StateRef = AccessTools.FieldRefAccess("currentMenuState"); internal static bool Visible; private static int _openFrame; private GUIStyle _title; private GUIStyle _row; private GUIStyle _key; internal static void Toggle() { Visible = !Visible; if (Visible) { _openFrame = Time.frameCount; } } private static bool MenuOpen() { MenuManager instance = MenuManager.instance; if ((Object)(object)instance != (Object)null) { return StateRef.Invoke(instance) == 0; } return false; } private void Update() { if (!Plugin.Enabled.Value) { Visible = false; return; } Gamepad current = Gamepad.current; if (current == null) { Visible = false; return; } if (Visible && Time.frameCount > _openFrame + 1 && (AnyButtonPressed(current) || MouseClicked())) { Visible = false; } if (!MenuOpen()) { Visible = false; } } private static bool MouseClicked() { Mouse current = Mouse.current; if (current != null) { if (!current.leftButton.wasPressedThisFrame) { return current.rightButton.wasPressedThisFrame; } return true; } return false; } private static bool AnyButtonPressed(Gamepad gp) { if (!gp.buttonSouth.wasPressedThisFrame && !gp.buttonEast.wasPressedThisFrame && !gp.buttonWest.wasPressedThisFrame && !gp.buttonNorth.wasPressedThisFrame && !gp.leftShoulder.wasPressedThisFrame && !gp.rightShoulder.wasPressedThisFrame && !gp.leftTrigger.wasPressedThisFrame && !gp.rightTrigger.wasPressedThisFrame && !gp.dpad.up.wasPressedThisFrame && !gp.dpad.down.wasPressedThisFrame && !gp.dpad.left.wasPressedThisFrame && !gp.dpad.right.wasPressedThisFrame && !gp.startButton.wasPressedThisFrame && !gp.selectButton.wasPressedThisFrame && !gp.leftStickButton.wasPressedThisFrame) { return gp.rightStickButton.wasPressedThisFrame; } return true; } private void OnGUI() { //IL_002d: 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_00ac: 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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0129: 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) if (!Visible) { return; } EnsureStyles(); List> list = Rows(ControllerDetect.Current); GUI.color = new Color(0f, 0f, 0f, 0.6f); GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)Texture2D.whiteTexture); float num = 520f; float num2 = 26f; float num3 = 60f + (float)list.Count * num2; float num4 = ((float)Screen.width - num) / 2f; float num5 = ((float)Screen.height - num3) / 2f; GUI.color = new Color(0.1f, 0.1f, 0.1f, 0.95f); GUI.DrawTexture(new Rect(num4, num5, num, num3), (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; GUI.Label(new Rect(num4, num5 + 12f, num, 30f), "Controller Layout", _title); float num6 = num5 + 50f; foreach (KeyValuePair item in list) { GUI.Label(new Rect(num4 + 24f, num6, num * 0.55f, num2), item.Key, _row); ControllerGlyphs.DrawLabel(new Rect(num4 + num * 0.55f, num6, num * 0.4f, num2), item.Value, _key); num6 += num2; } } private static List> Rows(ControllerDetect.Kind k) { List> list = new List>(); list.Add(R("Move / Look", N(ButtonNames.Control.LStick) + " / " + N(ButtonNames.Control.RStick))); list.Add(R("Jump", N(ButtonNames.Control.South))); list.Add(R("Interact", N(ButtonNames.Control.West))); list.Add(R("Tumble", N(ButtonNames.Control.East))); list.Add(R("Map", N(ButtonNames.Control.North))); list.Add(R("Sprint / Crouch", N(ButtonNames.Control.L3) + " / " + N(ButtonNames.Control.R3))); list.Add(R("Grab / Rotate", N(ButtonNames.Control.RT) + " / " + N(ButtonNames.Control.LT))); list.Add(R("Push / Pull", N(ButtonNames.Control.RB) + " / " + N(ButtonNames.Control.LB))); list.Add(R("Pause / Chat", N(ButtonNames.Control.Start) + " / " + N(ButtonNames.Control.Select))); list.Add(R("Inventory 1 / 2 / 3", N(ButtonNames.Control.DpadLeft) + " / " + N(ButtonNames.Control.DpadUp) + " / " + N(ButtonNames.Control.DpadRight))); list.Add(R("Emotes", "hold " + N(ButtonNames.Control.DpadDown))); list.Add(R("View this layout", "Settings menu")); list.Add(R("Menu: Select / Back", N(ButtonNames.Control.South) + " / " + N(ButtonNames.Control.East))); return list; string N(ButtonNames.Control c) { return ButtonNames.Of(c, k); } static KeyValuePair R(string a, string b) { return new KeyValuePair(a, b); } } private void EnsureStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_003f: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) if (_title == null) { _title = new GUIStyle(GUI.skin.label) { fontSize = 22, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; _title.normal.textColor = Color.white; _row = new GUIStyle(GUI.skin.label) { fontSize = 16 }; _row.normal.textColor = Color.white; _key = new GUIStyle(GUI.skin.label) { fontSize = 16, fontStyle = (FontStyle)1 }; _key.normal.textColor = new Color(1f, 0.85f, 0.3f); } } } internal class EmoteWheel : MonoBehaviour { private static readonly FieldRef MenuStateRef; private static readonly FieldRef ChatActiveRef; private static readonly Action DoExpression; private static readonly FieldRef ToggleMuteRef; internal static bool Open; private const int SegmentCount = 7; private const int ExpressionCount = 6; private const int MuteSegment = 7; private const float MinDeflection = 0.35f; private static readonly float[] SegmentAngles; private static readonly Dictionary Active; private static readonly List Expired; private static string[] _labels; private static bool _warned; private static bool _muteWarned; private int _hovered; private static Transform _previewCam; private static bool _camMoved; private static Vector3 _camHomeLocal; private GUIStyle _title; private GUIStyle _label; private GUIStyle _labelHover; private GUIStyle _labelActive; private GUIStyle _labelDisabled; static EmoteWheel() { MenuStateRef = AccessTools.FieldRefAccess("currentMenuState"); ChatActiveRef = AccessTools.FieldRefAccess("chatActive"); DoExpression = AccessTools.MethodDelegate>(AccessTools.Method(typeof(PlayerExpression), "DoExpression", (Type[])null, (Type[])null), (object)null, true); SegmentAngles = new float[8] { 0f, 15f, 45f, 75f, 105f, 135f, 165f, 270f }; Active = new Dictionary(); Expired = new List(); try { ToggleMuteRef = AccessTools.FieldRefAccess("toggleMute"); } catch { ToggleMuteRef = null; } } internal static void ResetState() { Active.Clear(); _labels = null; Open = false; _previewCam = null; _camMoved = false; } private void Update() { //IL_0056: 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) if (!Plugin.Enabled.Value || !Plugin.EmoteWheelEnabled.Value) { Close(); return; } Gamepad current = Gamepad.current; if (current == null || !InGameplay()) { Close(); return; } if (current.dpad.down.isPressed) { Open = true; _hovered = HoveredSegment(((InputControl)(object)current.rightStick).ReadValue()); } else if (Open) { int num = HoveredSegment(((InputControl)(object)current.rightStick).ReadValue()); if (num == 0) { num = _hovered; } Close(); switch (num) { case 7: ToggleMute(); break; default: ToggleExpression(num); break; case 0: break; } } DriveActiveExpressions(); } private void LateUpdate() { //IL_0059: 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_006b: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_004d: Unknown result type (might be due to invalid IL or missing references) if (!Open && Active.Count <= 0) { RestoreCamera(); return; } PlayerExpressionsUI instance = PlayerExpressionsUI.instance; if ((Object)(object)instance == (Object)null) { return; } Transform val = FindPreviewCamera(instance); if (!((Object)(object)val == (Object)null)) { if (!_camMoved) { _camHomeLocal = val.localPosition; _camMoved = true; } val.localPosition = _camHomeLocal; val.position += val.forward * (0f - Plugin.EmoteZoomOut.Value) + val.up * (0f - Plugin.EmoteCameraLower.Value); } } private static Transform FindPreviewCamera(PlayerExpressionsUI ui) { if ((Object)(object)_previewCam != (Object)null) { return _previewCam; } if ((Object)(object)ui.PlayerAvatarMenu == (Object)null) { return null; } PlayerAvatarMenu component = ui.PlayerAvatarMenu.GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component.cameraAndStuff == (Object)null) { return null; } Camera componentInChildren = ((Component)component.cameraAndStuff).GetComponentInChildren(true); if ((Object)(object)componentInChildren == (Object)null) { return null; } _previewCam = ((Component)componentInChildren).transform; return _previewCam; } private static void RestoreCamera() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (_camMoved) { _camMoved = false; if ((Object)(object)_previewCam != (Object)null) { _previewCam.localPosition = _camHomeLocal; } } } private static void DriveActiveExpressions() { if (Active.Count == 0) { return; } PlayerAvatar instance = PlayerAvatar.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerExpression == (Object)null) { return; } PlayerExpression val = (((Object)(object)PlayerExpressionsUI.instance != (Object)null) ? PlayerExpressionsUI.instance.playerExpression : null); Expired.Clear(); if (Plugin.EmoteDurationSeconds.Value > 0f) { foreach (int item in new List(Active.Keys)) { Active[item] -= Time.deltaTime; if (Active[item] <= 0f) { Expired.Add(item); } } foreach (int item2 in Expired) { Active.Remove(item2); } if (Active.Count == 0) { return; } } try { foreach (int key in Active.Keys) { DoExpression(instance.playerExpression, key, 100f, arg4: true); if ((Object)(object)val != (Object)null) { val.OverrideExpressionSet(key, 100f); } } } catch (Exception ex) { if (!_warned) { Plugin.Log.LogWarning((object)("[EmoteWheel] DoExpression failed: " + ex.Message)); _warned = true; } } } private void Close() { Open = false; _hovered = 0; } private static bool InGameplay() { MenuManager instance = MenuManager.instance; if ((Object)(object)instance != (Object)null && MenuStateRef.Invoke(instance) == 0) { return false; } ChatManager instance2 = ChatManager.instance; if ((Object)(object)instance2 != (Object)null && ChatActiveRef.Invoke(instance2)) { return false; } return (Object)(object)PlayerAvatar.instance != (Object)null; } private int HoveredSegment(Vector2 stick) { //IL_0021: 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) float num = Mathf.Max(Plugin.StickDeadzone.Value, 0.35f); if (((Vector2)(ref stick)).magnitude < num) { return 0; } float num2 = Mathf.Atan2(stick.x, stick.y) * 57.29578f; int result = 0; float num3 = float.MaxValue; for (int i = 1; i <= 7; i++) { float num4 = Mathf.Abs(Mathf.DeltaAngle(num2, SegmentAngles[i])); if (num4 < num3) { num3 = num4; result = i; } } return result; } private static void ToggleExpression(int index) { PlayerAvatar instance = PlayerAvatar.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerExpression == (Object)null) { return; } try { if (Active.Remove(index)) { Plugin.Log.LogDebug((object)$"[EmoteWheel] Expression {index} OFF"); return; } Active.Clear(); DoExpression(instance.playerExpression, index, 100f, arg4: true); float value = Plugin.EmoteDurationSeconds.Value; Active[index] = ((value > 0f) ? value : float.PositiveInfinity); Plugin.Log.LogDebug((object)$"[EmoteWheel] Expression {index} ON"); } catch (Exception ex) { if (!_warned) { Plugin.Log.LogWarning((object)("[EmoteWheel] Expression call failed: " + ex.Message)); _warned = true; } } } private static void ToggleMute() { if (!SemiFunc.IsMultiplayer()) { return; } DataDirector instance = DataDirector.instance; if ((Object)(object)instance == (Object)null) { return; } if (ToggleMuteRef == null) { if (!_muteWarned) { Plugin.Log.LogWarning((object)"[EmoteWheel] DataDirector.toggleMute not found -- mute slot disabled."); _muteWarned = true; } return; } try { ref bool reference = ref ToggleMuteRef.Invoke(instance); reference = !reference; Plugin.Log.LogDebug((object)("[EmoteWheel] Mic mute " + (reference ? "ON" : "OFF"))); } catch (Exception ex) { if (!_muteWarned) { Plugin.Log.LogWarning((object)("[EmoteWheel] Mute toggle failed: " + ex.Message)); _muteWarned = true; } } } private static bool IsMuted() { DataDirector instance = DataDirector.instance; if ((Object)(object)instance == (Object)null || ToggleMuteRef == null) { return false; } try { return ToggleMuteRef.Invoke(instance); } catch { return false; } } private void OnGUI() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_009a: 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_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0155: 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_0207: 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) if (!Open) { return; } EnsureStyles(); EnsureLabels(); float num = (float)Screen.width / 2f; float num2 = (float)Screen.height / 2f; float num3 = 190f; GUI.color = new Color(0f, 0f, 0f, 0.35f); GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; GUI.Label(new Rect(num - 200f, num2 - num3 - 70f, 400f, 30f), "Emotes", _title); Rect val = default(Rect); for (int i = 1; i <= 7; i++) { float num4 = SegmentAngles[i] * (MathF.PI / 180f); float num5 = num + Mathf.Sin(num4) * num3; float num6 = num2 - Mathf.Cos(num4) * num3; ((Rect)(ref val))..ctor(num5 - 80f, num6 - 20f, 160f, 40f); bool flag = i != 7 || SemiFunc.IsMultiplayer(); GUI.color = ((i == _hovered && flag) ? new Color(0.3f, 0.26f, 0.08f, 0.95f) : new Color(0.1f, 0.1f, 0.1f, 0.9f)); GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; if (i == 7) { bool num7 = SemiFunc.IsMultiplayer(); bool flag2 = num7 && IsMuted(); string text = ((!num7) ? "Mute (MP only)" : (flag2 ? "Unmute Mic" : "Mute Mic")); GUIStyle val2 = ((!num7) ? _labelDisabled : ((i == _hovered) ? _labelHover : (flag2 ? _labelActive : _label))); GUI.Label(val, text, val2); } else { GUIStyle val3 = ((i == _hovered) ? _labelHover : (Active.ContainsKey(i) ? _labelActive : _label)); GUI.Label(val, _labels[i], val3); } } } private static void EnsureLabels() { if (_labels != null) { return; } _labels = new string[8]; List list = null; PlayerAvatar instance = PlayerAvatar.instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.playerExpression != (Object)null) { list = instance.playerExpression.expressions; } for (int i = 1; i <= 6; i++) { string text = null; if (list != null && i < list.Count && list[i] != null) { text = list[i].expressionName; } _labels[i] = (string.IsNullOrEmpty(text) ? $"Expression {i}" : text); } } private void EnsureStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_003f: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_0078: 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_009a: Expected O, but got Unknown //IL_00b4: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown //IL_0125: Unknown result type (might be due to invalid IL or missing references) if (_title == null) { _title = new GUIStyle(GUI.skin.label) { fontSize = 22, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; _title.normal.textColor = Color.white; _label = new GUIStyle(GUI.skin.label) { fontSize = 16, alignment = (TextAnchor)4 }; _label.normal.textColor = Color.white; _labelHover = new GUIStyle(_label) { fontStyle = (FontStyle)1 }; _labelHover.normal.textColor = new Color(1f, 0.85f, 0.3f); _labelActive = new GUIStyle(_label) { fontStyle = (FontStyle)1 }; _labelActive.normal.textColor = new Color(0.55f, 0.8f, 1f); _labelDisabled = new GUIStyle(_label); _labelDisabled.normal.textColor = new Color(0.5f, 0.5f, 0.5f); } } } internal enum PadButton { None, South, East, West, North, LB, RB, LT, RT, L3, R3, DpadLeft, DpadUp, DpadRight, DpadDown, Start, Select } [HarmonyPatch] internal static class GamepadBindingsPatch { private static InputManager _injected; private static string _pttPath; private static string PathOf(PadButton b) { return b switch { PadButton.South => "/buttonSouth", PadButton.East => "/buttonEast", PadButton.West => "/buttonWest", PadButton.North => "/buttonNorth", PadButton.LB => "/leftShoulder", PadButton.RB => "/rightShoulder", PadButton.LT => "/leftTrigger", PadButton.RT => "/rightTrigger", PadButton.L3 => "/leftStickPress", PadButton.R3 => "/rightStickPress", PadButton.DpadLeft => "/dpad/left", PadButton.DpadUp => "/dpad/up", PadButton.DpadRight => "/dpad/right", PadButton.DpadDown => "/dpad/down", PadButton.Start => "/start", PadButton.Select => "/select", _ => null, }; } [HarmonyPatch(typeof(InputManager), "InitializeInputs")] [HarmonyPostfix] public static void Postfix(InputManager __instance) { if (!Plugin.Enabled.Value || _injected == __instance) { return; } _injected = __instance; try { Bind(__instance, (InputKey)0, "/leftStick"); Bind(__instance, (InputKey)1, "/buttonSouth"); Bind(__instance, (InputKey)2, "/buttonWest"); Bind(__instance, (InputKey)14, "/buttonEast"); Bind(__instance, (InputKey)8, "/buttonNorth"); Bind(__instance, (InputKey)15, "/leftStickPress"); Bind(__instance, (InputKey)12, "/rightStickPress"); Bind(__instance, (InputKey)10, "/rightTrigger"); Bind(__instance, (InputKey)11, "/leftTrigger"); Bind(__instance, (InputKey)6, "/start"); Bind(__instance, (InputKey)7, "/select"); Bind(__instance, (InputKey)13, "/buttonEast"); Bind(__instance, (InputKey)19, "/dpad/left"); Bind(__instance, (InputKey)20, "/dpad/up"); Bind(__instance, (InputKey)21, "/dpad/right"); if (Plugin.PushToTalkButton.Value != PadButton.None) { _pttPath = PathOf(Plugin.PushToTalkButton.Value); Bind(__instance, (InputKey)25, _pttPath); } else { _pttPath = null; } Plugin.Log.LogInfo((object)"[Gamepad] Bindings injected."); } catch (Exception arg) { Plugin.Log.LogError((object)$"[Gamepad] Binding injection failed: {arg}"); } } [HarmonyPatch(typeof(InputManager), "LoadKeyBindings")] [HarmonyPostfix] public static void LoadKeyBindingsPostfix() { if (Plugin.Enabled.Value) { RebindPushToTalk(); } } [HarmonyPatch(typeof(InputManager), "ResetKeyToDefault")] [HarmonyPostfix] public static void ResetKeyToDefaultPostfix(InputKey key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 if ((int)key == 25 && Plugin.Enabled.Value) { RebindPushToTalk(); } } internal static void RebindPushToTalk() { //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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) //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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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) if ((Object)(object)_injected == (Object)null) { return; } try { InputAction action = _injected.GetAction((InputKey)25); if (action == null) { return; } bool enabled = action.enabled; if (enabled) { action.Disable(); } try { if (_pttPath != null) { for (int i = 0; i < action.bindings.Count; i++) { InputBinding val = action.bindings[i]; if (((InputBinding)(ref val)).path == _pttPath) { BindingSyntax val2 = InputActionSetupExtensions.ChangeBinding(action, i); ((BindingSyntax)(ref val2)).Erase(); break; } } _pttPath = null; } PadButton value = Plugin.PushToTalkButton.Value; if (value != PadButton.None) { _pttPath = PathOf(value); InputActionSetupExtensions.AddBinding(action, _pttPath, (string)null, (string)null, (string)null); } } finally { if (enabled) { action.Enable(); } } Plugin.Log.LogInfo((object)$"[Gamepad] PushToTalk binding -> {Plugin.PushToTalkButton.Value}."); } catch (Exception arg) { Plugin.Log.LogError((object)$"[Gamepad] PushToTalk rebind failed: {arg}"); } } internal static void Bind(InputManager im, InputKey key, string path, string processors = null) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_0058: 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) InputAction action = im.GetAction(key); if (action == null) { Plugin.Log.LogWarning((object)$"[Gamepad] No action for {key}"); return; } bool enabled = action.enabled; if (enabled) { action.Disable(); } if (string.IsNullOrEmpty(processors)) { InputActionSetupExtensions.AddBinding(action, path, (string)null, (string)null, (string)null); } else { BindingSyntax val = InputActionSetupExtensions.AddBinding(action, path, (string)null, (string)null, (string)null); ((BindingSyntax)(ref val)).WithProcessors(processors); } if (enabled) { action.Enable(); } } } internal class GrabPromptOverlay : MonoBehaviour { private struct Prompt { public string Rich; public string Plain; } private struct SlotLabel { public TextMeshProUGUI Text; public string Original; public int SpotIndex; } private static readonly FieldRef MenuStateRef = AccessTools.FieldRefAccess("currentMenuState"); private static FieldRef _aimStateRef; private static bool _aimRefFailed; private ControllerDetect.Kind _cachedKind = (ControllerDetect.Kind)(-1); private Prompt _grab; private Prompt _letGo; private Prompt _rotate; private Prompt _climb; private Prompt _rightLine; private Prompt _leftLine; private GUIStyle _style; private bool _showArrows; private bool _labelsSwapped; private InventorySpot[] _spots; private readonly Vector3[] _corners = (Vector3[])(object)new Vector3[4]; private readonly List _slotLabels = new List(8); private void Update() { //IL_00bb: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected I4, but got Unknown ControllerDetect.TrackActiveInput(); InputDisplayPatch.TickCacheInvalidation(); _rightLine = default(Prompt); _leftLine = default(Prompt); _showArrows = false; if (!Plugin.Enabled.Value || !Plugin.PromptsEnabled.Value || Gamepad.current == null || !ControllerDetect.PadActive || EmoteWheel.Open) { return; } MenuManager instance = MenuManager.instance; if ((Object)(object)instance != (Object)null && MenuStateRef.Invoke(instance) == 0) { return; } _showArrows = Plugin.InventoryArrows.Value && ControllerDetect.PadTouchedThisLevel; Aim instance2 = Aim.instance; if ((Object)(object)instance2 == (Object)null || !EnsureAimRef()) { return; } EnsureNames(); State val = _aimStateRef.Invoke(instance2); switch (val - 1) { case 0: _rightLine = _grab; break; case 1: case 2: if (Plugin.GrabToggle.Value) { _rightLine = _letGo; } _leftLine = _rotate; break; case 4: _rightLine = _climb; break; case 3: break; } } private static bool EnsureAimRef() { if (_aimStateRef != null) { return true; } if (_aimRefFailed) { return false; } try { _aimStateRef = AccessTools.FieldRefAccess("currentState"); return true; } catch (Exception ex) { _aimRefFailed = true; Plugin.Log.LogWarning((object)("[Prompts] Aim.currentState unavailable — prompts disabled: " + ex.Message)); return false; } } private void EnsureNames() { ControllerDetect.Kind current = ControllerDetect.Current; if (current != _cachedKind || _grab.Plain == null) { _cachedKind = current; string button = ButtonNames.Of(ButtonNames.Control.RT, current); string button2 = ButtonNames.Of(ButtonNames.Control.LT, current); _grab = Make("GRAB", button); _letGo = Make("LET GO", button); _rotate = Make("ROTATE", button2); _climb = Make("CLIMB", button); } } private static Prompt Make(string action, string button) { return new Prompt { Rich = "" + action + " [" + button + "]", Plain = action + " [" + button + "]" }; } private void LateUpdate() { if (!_showArrows && !_labelsSwapped) { return; } if (NeedSlotLabelRefresh()) { _slotLabels.Clear(); _labelsSwapped = false; _spots = Object.FindObjectsOfType(); InventorySpot[] spots = _spots; foreach (InventorySpot val in spots) { int inventorySpotIndex = val.inventorySpotIndex; if (inventorySpotIndex < 0 || inventorySpotIndex > 2) { continue; } string text = (inventorySpotIndex + 1).ToString(); TextMeshProUGUI[] componentsInChildren = ((Component)val).GetComponentsInChildren(true); foreach (TextMeshProUGUI val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)(object)val.noItem || ((TMP_Text)val2).text.Trim() == text) { _slotLabels.Add(new SlotLabel { Text = val2, Original = ((TMP_Text)val2).text, SpotIndex = inventorySpotIndex }); } } } if (_slotLabels.Count == 0) { return; } } ControllerDetect.Kind current = ControllerDetect.Current; foreach (SlotLabel slotLabel in _slotLabels) { if ((Object)(object)slotLabel.Text == (Object)null) { continue; } if (_showArrows) { string text2 = ((slotLabel.SpotIndex == 0) ? ButtonNames.Of(ButtonNames.Control.DpadLeft, current) : ((slotLabel.SpotIndex == 1) ? ButtonNames.Of(ButtonNames.Control.DpadUp, current) : ButtonNames.Of(ButtonNames.Control.DpadRight, current))); if (((TMP_Text)slotLabel.Text).text != text2) { ((TMP_Text)slotLabel.Text).text = text2; } } else if (((TMP_Text)slotLabel.Text).text != slotLabel.Original) { ((TMP_Text)slotLabel.Text).text = slotLabel.Original; } } _labelsSwapped = _showArrows; } private bool NeedSlotLabelRefresh() { if (_spots == null || _spots.Length == 0 || (Object)(object)_spots[0] == (Object)null || _slotLabels.Count == 0) { return true; } foreach (SlotLabel slotLabel in _slotLabels) { if ((Object)(object)slotLabel.Text == (Object)null) { return true; } } return false; } private void OnGUI() { if (_rightLine.Plain == null && _leftLine.Plain == null) { return; } EnsureStyles(); if (TryInventoryScreenBounds(out var minX, out var maxX, out var centerY)) { float guiCenterY = (float)Screen.height - centerY; if (_rightLine.Plain != null) { DrawChip(_rightLine, maxX + 14f, guiCenterY, rightSide: true); } if (_leftLine.Plain != null) { DrawChip(_leftLine, minX - 14f, guiCenterY, rightSide: false); } return; } float cx = (float)Screen.width / 2f; float num = (float)Screen.height / 2f + 35f; if (_rightLine.Plain != null) { DrawChipCentered(_rightLine, cx, num); num += 28f; } if (_leftLine.Plain != null) { DrawChipCentered(_leftLine, cx, num); } } private void DrawChip(Prompt p, float anchorX, float guiCenterY, bool rightSide) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0011: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) float num = _style.CalcSize(new GUIContent(p.Plain)).x + 18f; Rect val = new Rect(rightSide ? anchorX : (anchorX - num), guiCenterY - 12f, num, 24f); GUI.color = new Color(0.08f, 0.08f, 0.08f, 0.85f); GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; GUI.Label(val, p.Rich, _style); } private void DrawChipCentered(Prompt p, float cx, float y) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0011: 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_004b: 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) //IL_0060: Unknown result type (might be due to invalid IL or missing references) float num = _style.CalcSize(new GUIContent(p.Plain)).x + 18f; Rect val = new Rect(cx - num / 2f, y, num, 24f); GUI.color = new Color(0.08f, 0.08f, 0.08f, 0.85f); GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; GUI.Label(val, p.Rich, _style); } private bool TryInventoryScreenBounds(out float minX, out float maxX, out float centerY) { //IL_00a9: 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_00c0: 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_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: 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_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0152: 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_015f: Unknown result type (might be due to invalid IL or missing references) minX = float.MaxValue; maxX = float.MinValue; centerY = 0f; CameraOverlay instance = CameraOverlay.instance; RenderTextureMain instance2 = RenderTextureMain.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || (Object)(object)instance2.overlayRawImage == (Object)null) { return false; } Camera component = ((Component)instance).GetComponent(); if ((Object)(object)component == (Object)null) { return false; } if (_spots == null || _spots.Length == 0 || (Object)(object)_spots[0] == (Object)null) { _spots = Object.FindObjectsOfType(); if (_spots.Length == 0) { return false; } } ((Graphic)instance2.overlayRawImage).rectTransform.GetWorldCorners(_corners); Vector2 val = Vector2.op_Implicit(_corners[0]); Vector2 val2 = Vector2.op_Implicit(_corners[2]); float num = 0f; int num2 = 0; InventorySpot[] spots = _spots; foreach (InventorySpot val3 in spots) { if ((Object)(object)val3 == (Object)null) { continue; } Transform transform = ((Component)val3).transform; RectTransform val4 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val4 == (Object)null) { continue; } val4.GetWorldCorners(_corners); for (int j = 0; j < 4; j++) { Vector3 val5 = component.WorldToViewportPoint(_corners[j]); float num3 = Mathf.Lerp(val.x, val2.x, val5.x); float num4 = Mathf.Lerp(val.y, val2.y, val5.y); if (num3 < minX) { minX = num3; } if (num3 > maxX) { maxX = num3; } num += num4; } num2++; } if (num2 == 0) { return false; } centerY = num / (float)(num2 * 4); return true; } private void EnsureStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (_style == null) { _style = new GUIStyle(GUI.skin.label) { fontSize = 14, fontStyle = (FontStyle)1, alignment = (TextAnchor)4, richText = true }; _style.normal.textColor = Color.white; } } } [HarmonyPatch] internal static class InputDisplayPatch { private static readonly FieldRef MenuStateRef = AccessTools.FieldRefAccess("currentMenuState"); private static readonly FieldRef ItemTagRef = AccessTools.FieldRefAccess("itemTag"); private static bool _lastControllerActive; [HarmonyPatch(typeof(InputManager), "InputDisplayGet")] [HarmonyPostfix] private static void InputDisplayGetPostfix(InputKey _inputKey, KeyType _keyType, MovementDirection _movementDirection, ref string __result) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Invalid comparison between Unknown and I4 //IL_005c: 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) if (!Plugin.Enabled.Value || !Plugin.ControllerKeyTags.Value || Gamepad.current == null || !ControllerDetect.PadActive) { return; } MenuManager instance = MenuManager.instance; if ((Object)(object)instance != (Object)null && MenuStateRef.Invoke(instance) == 0) { return; } if ((int)_keyType == 1) { __result = (((int)_movementDirection == 0) ? "L-STICK" : ""); return; } string text = NameFor(_inputKey, ControllerDetect.Current); if (text != null) { __result = text.ToUpper(); } } private static string NameFor(InputKey key, ControllerDetect.Kind kind) { //IL_0000: 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_0084: Expected I4, but got Unknown switch (key - 1) { case 0: return B(ButtonNames.Control.South, kind); case 1: return B(ButtonNames.Control.West, kind); case 13: return B(ButtonNames.Control.East, kind); case 7: return B(ButtonNames.Control.North, kind); case 14: return "L3"; case 11: return "R3"; case 9: return B(ButtonNames.Control.RT, kind); case 10: return B(ButtonNames.Control.LT, kind); case 5: return B(ButtonNames.Control.Start, kind); case 6: return B(ButtonNames.Control.Select, kind); case 18: return B(ButtonNames.Control.DpadLeft, kind); case 19: return B(ButtonNames.Control.DpadUp, kind); case 20: return B(ButtonNames.Control.DpadRight, kind); case 3: return B(ButtonNames.Control.RB, kind); case 4: return B(ButtonNames.Control.LB, kind); case 25: case 26: case 27: case 28: case 29: case 30: return B(ButtonNames.Control.DpadDown, kind) + " (wheel)"; default: return null; } } private static string B(ButtonNames.Control c, ControllerDetect.Kind kind) { return ButtonNames.Of(c, kind); } internal static void TickCacheInvalidation() { if (!Plugin.Enabled.Value || !Plugin.ControllerKeyTags.Value) { return; } bool flag = ControllerDetect.PadActive && Gamepad.current != null; if (flag == _lastControllerActive) { return; } _lastControllerActive = flag; try { ItemAttributes[] array = Object.FindObjectsOfType(); foreach (ItemAttributes val in array) { ItemTagRef.Invoke(val) = ""; } } catch (Exception ex) { Plugin.Log.LogDebug((object)("[Prompts] item tag cache clear failed: " + ex.Message)); } } } [HarmonyPatch(typeof(InputManager))] internal static class LookPatch { private const float AimSpeedFloor = 0.0001f; [HarmonyPatch("GetMouseX")] [HarmonyPostfix] public static void GetMouseXPostfix(ref float __result) { //IL_002c: 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_009f: 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) //IL_00af: 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_00b7: 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_00c3: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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_00f2: 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_00ff: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.Enabled.Value || EmoteWheel.Open || ChatKeyboard.Open) { return; } Gamepad current = Gamepad.current; if (current != null) { float num = Deadzone(((InputControl)(object)current.rightStick).ReadValue().x); if (Plugin.InvertX.Value) { num = 0f - num; } __result += num * Plugin.LookSpeedX.Value; } if (!Plugin.AimAssistEnabled.Value || !AimAssist.HasTarget) { return; } CameraAim instance = CameraAim.Instance; Camera main = Camera.main; if (!((Object)(object)instance == (Object)null) && !((Object)(object)main == (Object)null)) { Vector3 forward = ((Component)main).transform.forward; Vector3 val = AimAssist.TargetPosition - ((Component)main).transform.position; Vector3 val2 = Vector3.ProjectOnPlane(forward, Vector3.up); Vector3 val3 = Vector3.ProjectOnPlane(val, Vector3.up); if (!(((Vector3)(ref val2)).sqrMagnitude < 0.0001f) && !(((Vector3)(ref val3)).sqrMagnitude < 0.0001f)) { float axisErrDeg = Vector3.SignedAngle(val2, val3, Vector3.up); float totalErrDeg = Vector3.Angle(forward, val); __result += Correction(axisErrDeg, totalErrDeg, __result, instance.AimSpeedMouse); } } } [HarmonyPatch("GetMouseY")] [HarmonyPostfix] public static void GetMouseYPostfix(ref float __result) { //IL_002c: 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_009f: 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) //IL_00af: 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_00b8: 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_0109: 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) if (!Plugin.Enabled.Value || EmoteWheel.Open || ChatKeyboard.Open) { return; } Gamepad current = Gamepad.current; if (current != null) { float num = Deadzone(((InputControl)(object)current.rightStick).ReadValue().y); if (Plugin.InvertY.Value) { num = 0f - num; } __result += num * Plugin.LookSpeedY.Value; } if (Plugin.AimAssistEnabled.Value && AimAssist.HasTarget) { CameraAim instance = CameraAim.Instance; Camera main = Camera.main; if (!((Object)(object)instance == (Object)null) && !((Object)(object)main == (Object)null)) { Vector3 forward = ((Component)main).transform.forward; Vector3 val = AimAssist.TargetPosition - ((Component)main).transform.position; float num2 = Mathf.Asin(Mathf.Clamp(((Vector3)(ref val)).normalized.y, -1f, 1f)) * 57.29578f; float num3 = Mathf.Asin(Mathf.Clamp(((Vector3)(ref forward)).normalized.y, -1f, 1f)) * 57.29578f; float axisErrDeg = num2 - num3; float totalErrDeg = Vector3.Angle(forward, val); __result += Correction(axisErrDeg, totalErrDeg, __result, instance.AimSpeedMouse); } } } private static float Correction(float axisErrDeg, float totalErrDeg, float playerResult, float aimSpeed) { aimSpeed = Mathf.Max(0.0001f, aimSpeed); float value = Plugin.AimAssistDeadZone.Value; float value2 = Plugin.AimAssistMaxAngle.Value; float num = ((totalErrDeg <= value) ? 0f : ((!(totalErrDeg >= value2)) ? Mathf.SmoothStep(0f, 1f, (totalErrDeg - value) / Mathf.Max(0.001f, value2 - value)) : 1f)); if (num <= 0f) { return 0f; } float num2 = Plugin.AimAssistGain.Value * axisErrDeg * num; float num3 = Mathf.Abs(playerResult) * aimSpeed; float num4 = ((!(num3 > Plugin.AimAssistActiveThreshold.Value)) ? Mathf.Min(Plugin.AimAssistIdleDrift.Value * num, Plugin.AimAssistMaxDegPerFrame.Value) : Mathf.Min(Plugin.AimAssistMaxFraction.Value * num3, Plugin.AimAssistMaxDegPerFrame.Value)); return Mathf.Clamp(num2, 0f - num4, num4) / aimSpeed; } private static float Deadzone(float v) { float value = Plugin.StickDeadzone.Value; if (!(Mathf.Abs(v) < value)) { return v; } return 0f; } } [HarmonyPatch(typeof(MenuButton), "ProcessHover")] internal static class MenuButtonHoverPatch { private static readonly FieldRef HoveringRef = AccessTools.FieldRefAccess("hovering"); private static readonly FieldInfo ButtonTextField = AccessTools.Field(typeof(MenuButton), "buttonText"); private static PropertyInfo s_colorProp; [HarmonyPostfix] public static void Postfix(MenuButton __instance) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) if (!MenuNavigator.ControllerActive) { return; } bool flag = __instance == MenuNavigator.Selected; HoveringRef.Invoke(__instance) = flag; object obj = ((ButtonTextField != null) ? ButtonTextField.GetValue(__instance) : null); if (obj != null) { if (s_colorProp == null) { s_colorProp = obj.GetType().GetProperty("color"); } s_colorProp?.SetValue(obj, flag ? __instance.colorHover : __instance.colorNormal); } if (flag) { __instance.OnHovering(); } } } [HarmonyPatch(typeof(MenuCursor), "Show")] internal static class MenuCursorHidePatch { [HarmonyPrefix] private static bool Prefix() { if (!Plugin.Enabled.Value || !Plugin.HideMouseCursorOnPad.Value) { return true; } return !MenuNavigator.ControllerActive; } } internal class MenuKeyboard : MonoBehaviour { private static readonly FieldRef TextInputActiveRef = AccessTools.FieldRefAccess("textInputActive"); private static readonly FieldRef TextCurrentRef = AccessTools.FieldRefAccess("textCurrent"); private static readonly FieldRef PasswordRef = AccessTools.FieldRefAccess("password"); internal static bool Open; private PadKeyboardCore _core; private bool _coreHasSpace; private MenuTextInput _textInput; private MenuPagePassword _password; private bool _dismissed; private bool _selectArmed; private static bool _warned; internal static void ResetState() { Open = false; } private void Update() { MenuManager instance = MenuManager.instance; Gamepad current = Gamepad.current; if ((Object)(object)instance == (Object)null || current == null || !Plugin.Enabled.Value || !Plugin.MenuKeyboardEnabled.Value) { Open = false; return; } bool flag; try { flag = TextInputActiveRef.Invoke(instance); } catch (Exception e) { WarnOnce(e); Open = false; return; } if (!flag) { Open = false; _dismissed = false; _textInput = null; _password = null; return; } if (!Open && !_dismissed && MenuNavigator.ControllerActive) { try { if (AcquireTarget()) { OpenPanel(); } } catch (Exception e2) { WarnOnce(e2); return; } } if (!Open) { return; } if (!MenuNavigator.ControllerActive) { Open = false; return; } if (((Object)(object)_password != (Object)null && !((Behaviour)_password).isActiveAndEnabled) || ((Object)(object)_password == (Object)null && ((Object)(object)_textInput == (Object)null || !((Behaviour)_textInput).isActiveAndEnabled))) { Open = false; _textInput = null; _password = null; return; } if (!current.selectButton.isPressed && !current.selectButton.wasReleasedThisFrame) { _selectArmed = true; } try { _core.HandleInput(current); if (current.buttonEast.wasPressedThisFrame) { Backspace(); } if (_selectArmed && current.selectButton.wasReleasedThisFrame) { Dismiss(); } } catch (Exception e3) { WarnOnce(e3); } } private bool AcquireTarget() { _password = null; _textInput = null; MenuPagePassword[] array = Object.FindObjectsOfType(); foreach (MenuPagePassword val in array) { if (((Behaviour)val).isActiveAndEnabled) { _password = val; break; } } if ((Object)(object)_password == (Object)null) { MenuTextInput[] array2 = Object.FindObjectsOfType(); foreach (MenuTextInput val2 in array2) { if (((Behaviour)val2).isActiveAndEnabled) { _textInput = val2; break; } } } if (!((Object)(object)_password != (Object)null)) { return (Object)(object)_textInput != (Object)null; } return true; } private void OpenPanel() { bool flag = (Object)(object)_password == (Object)null; if (_core == null || _coreHasSpace != flag) { _core = new PadKeyboardCore(flag, "ENTER", "HIDE"); _core.OnChar = TypeChar; _core.OnConfirm = Confirm; _core.OnClose = Dismiss; _coreHasSpace = flag; } _core.Reset(); _selectArmed = false; Open = true; } private void TypeChar(string s) { if ((Object)(object)_password != (Object)null) { if (!(s == " ")) { PasswordRef.Invoke(_password) = PasswordRef.Invoke(_password) + s; } } else if ((Object)(object)_textInput != (Object)null) { string text = TextCurrentRef.Invoke(_textInput) ?? ""; if (text == "\b") { text = ""; } TextCurrentRef.Invoke(_textInput) = text + s; } } private void Backspace() { if ((Object)(object)_password != (Object)null) { string text = PasswordRef.Invoke(_password) ?? ""; if (text.Length > 0) { PasswordRef.Invoke(_password) = text.Remove(text.Length - 1); } } else if ((Object)(object)_textInput != (Object)null) { string text2 = TextCurrentRef.Invoke(_textInput) ?? ""; if (!(text2 == "\b") && text2.Length != 0) { TextCurrentRef.Invoke(_textInput) = text2.Remove(text2.Length - 1); } } } private void Confirm() { if ((Object)(object)_password != (Object)null) { _password.ConfirmButton(); } else { if ((Object)(object)_textInput == (Object)null) { return; } MenuPageServerListCreateNew val = FindPage(); if ((Object)(object)val != (Object)null) { val.ButtonConfirm(); return; } MenuPageSavesRename val2 = FindPage(); if ((Object)(object)val2 != (Object)null) { val2.ButtonConfirm(); return; } MenuPageServerListSearch val3 = FindPage(); if ((Object)(object)val3 != (Object)null) { val3.ButtonConfirm(); } else { WarnOnce(new Exception("active MenuTextInput has no known confirm owner")); } } } private T FindPage() where T : MonoBehaviour { if ((Object)(object)_textInput == (Object)null) { return default(T); } T componentInParent = ((Component)_textInput).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { return componentInParent; } T[] array = Object.FindObjectsOfType(); foreach (T val in array) { if (((Behaviour)(object)val).isActiveAndEnabled) { return val; } } return default(T); } private void Dismiss() { Open = false; _dismissed = true; } private static void WarnOnce(Exception e) { if (!_warned) { _warned = true; Plugin.Log.LogWarning((object)("[MenuKeyboard] Error (further warnings suppressed): " + e.Message)); } } private void OnGUI() { if (Open && _core != null) { _core.Draw(Plugin.ChatScale.Value, 40f * Plugin.ChatScale.Value); } } } internal class MenuNavigator : MonoBehaviour { private struct NavEntry { public MenuButton Btn; public MenuElementHover Hover; public Vector2 Pos; public Vector2 Min; public Vector2 Max; } private enum PickMode { Beam, Cone, Any } private static readonly FieldRef StateRef = AccessTools.FieldRefAccess("currentMenuState"); private static readonly FieldRef> ButtonsRef = AccessTools.FieldRefAccess>("allMenuButtons"); private static readonly FieldRef CurrentPageRef = AccessTools.FieldRefAccess("currentMenuPage"); private static readonly FieldRef> AddedPagesRef = AccessTools.FieldRefAccess>("addedPagesOnTop"); private static readonly FieldRef AddedOnTopRef = AccessTools.FieldRefAccess("addedPageOnTop"); private static readonly FieldRef ParentPageRef = AccessTools.FieldRefAccess("parentPage"); private static readonly FieldRef DisabledRef = AccessTools.FieldRefAccess("disabled"); private static readonly FieldRef HoveringRef = AccessTools.FieldRefAccess("hovering"); private static readonly FieldRef PageStateRef = AccessTools.FieldRefAccess("currentPageState"); private static readonly MethodInfo OnSelectMethod = AccessTools.Method(typeof(MenuButton), "OnSelect", (Type[])null, (Type[])null); private static readonly FieldInfo ButtonTextField = AccessTools.Field(typeof(MenuButton), "buttonText"); private static PropertyInfo s_textProp; private static readonly Vector3[] s_corners = (Vector3[])(object)new Vector3[4]; internal static MenuButton Selected; internal static bool ControllerActive; internal static RectTransform SelectedHoverRect; internal static float SnapSelectionBoxUntil; private const float SnapJumpDistance = 150f; private static readonly FieldRef SaveFileNameRef = AccessTools.FieldRefAccess("saveFileName"); private static readonly FieldRef> SaveFileBackupsRef = AccessTools.FieldRefAccess>("saveFileBackups"); private static readonly FieldRef SpringVelocityRef = AccessTools.FieldRefAccess("springVelocity"); private MenuButton _selected; private MenuElementHover _selectedHover; private bool _active; private float _navCooldown; private GUIStyle _style; private MenuPage _focusPage; private MenuPage _focusOverride; private MenuPage _lastTop; private readonly Dictionary _lastByPage = new Dictionary(); private static FieldInfo s_repoLastClicked; private static bool s_repoLookupDone; private bool MenuOpen(out MenuManager mm) { mm = MenuManager.instance; if ((Object)(object)mm != (Object)null) { return StateRef.Invoke(mm) == 0; } return false; } private void Update() { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) ControllerActive = false; Selected = null; SelectedHoverRect = null; if (!Plugin.Enabled.Value) { return; } Gamepad current = Gamepad.current; if (current == null) { return; } if (!MenuOpen(out var mm)) { _selected = null; _selectedHover = null; _focusOverride = null; _focusPage = null; _lastTop = null; _lastByPage.Clear(); return; } ResolveFocus(mm); List list = Candidates(mm, _focusPage); List list2 = HoverCandidates(_focusPage); if (list.Count == 0 && list2.Count == 0) { _selected = null; _selectedHover = null; return; } if (AnyControllerInput(current)) { _active = true; } if (Mouse.current != null) { Vector2 val = ((InputControl)(object)((Pointer)Mouse.current).delta).ReadValue(); if (((Vector2)(ref val)).sqrMagnitude > 4f) { _active = false; } } if (_active) { if (MenuKeyboard.Open) { Selected = _selected; ControllerActive = true; return; } bool num = (Object)(object)_selectedHover == (Object)null && (Object)(object)_selected != (Object)null && list.Contains(_selected); bool flag = (Object)(object)_selectedHover != (Object)null && list2.Contains(_selectedHover); if (!num && !flag) { _selected = null; _selectedHover = null; if ((Object)(object)_focusPage != (Object)null && _lastByPage.TryGetValue(_focusPage, out var value) && (Object)(object)value != (Object)null && list.Contains(value)) { _selected = value; } else { PickTopmost(list, list2, out _selected, out _selectedHover); } } HandleNavigation(current, list, list2); if (current.buttonSouth.wasPressedThisFrame) { if ((Object)(object)_selectedHover != (Object)null) { ActivateHover(_selectedHover); } else { Select(_selected); } } if (current.buttonEast.wasPressedThisFrame) { Back(list); } if ((Object)(object)_focusPage != (Object)null && (Object)(object)_selected != (Object)null && (Object)(object)_selectedHover == (Object)null) { _lastByPage[_focusPage] = _selected; } Selected = (((Object)(object)_selectedHover == (Object)null) ? _selected : null); SelectedHoverRect = (RectTransform)(((Object)(object)_selectedHover != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); ControllerActive = true; } else { MenuButton val2 = ((IEnumerable)list).FirstOrDefault((Func)((MenuButton b) => HoveringRef.Invoke(b))); if ((Object)(object)val2 != (Object)null) { _selected = val2; _selectedHover = null; } } } private static bool AnyControllerInput(Gamepad gp) { //IL_004e: 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) if (!gp.dpad.up.isPressed && !gp.dpad.down.isPressed && !gp.dpad.left.isPressed && !gp.dpad.right.isPressed) { Vector2 val = ((InputControl)(object)gp.leftStick).ReadValue(); if (!(((Vector2)(ref val)).sqrMagnitude > 0.2f) && !gp.buttonSouth.wasPressedThisFrame && !gp.buttonEast.wasPressedThisFrame) { return gp.selectButton.wasPressedThisFrame; } } return true; } private MenuPage DefaultFocus(MenuManager mm) { List list = AddedPagesRef.Invoke(mm); if (list != null) { for (int num = list.Count - 1; num >= 0; num--) { if (IsFocusableAdded(list[num])) { return list[num]; } } } return CurrentPageRef.Invoke(mm); } private bool IsLive(MenuManager mm, MenuPage p) { if ((Object)(object)p == (Object)null) { return false; } if ((Object)(object)p == (Object)(object)CurrentPageRef.Invoke(mm)) { return IsActivePage(p); } List list = AddedPagesRef.Invoke(mm); if (list != null && list.Contains(p)) { return IsFocusableAdded(p); } return false; } private void ResolveFocus(MenuManager mm) { MenuPage val = DefaultFocus(mm); if ((Object)(object)val != (Object)(object)_lastTop) { _focusOverride = null; _lastTop = val; } if ((Object)(object)_focusOverride != (Object)null && !IsLive(mm, _focusOverride)) { _focusOverride = null; } MenuPage val2 = _focusOverride ?? val; if ((Object)(object)val2 != (Object)(object)_focusPage) { _focusPage = val2; _selected = null; } } private List Candidates(MenuManager mm, MenuPage focus) { List list = ButtonsRef.Invoke(mm); List list2 = new List(); if (list == null) { return list2; } if ((Object)(object)focus != (Object)null) { foreach (MenuButton item in list) { if (Usable(item)) { MenuPage val = ParentPageRef.Invoke(item); if ((Object)(object)val == (Object)(object)focus || ((Object)(object)val == (Object)null && (Object)(object)((Component)item).GetComponentInParent() == (Object)(object)focus)) { list2.Add(item); } } } if (list2.Count > 0) { AddCulledScrollRows(list2); return list2; } } foreach (MenuButton item2 in list) { if (Usable(item2)) { MenuPage val2 = ParentPageRef.Invoke(item2); if ((Object)(object)val2 == (Object)null || AddedOnTopRef.Invoke(val2) || IsActivePage(val2)) { list2.Add(item2); } } } return list2; } private static void AddCulledScrollRows(List list) { MenuScrollBox val = null; for (int i = 0; i < list.Count; i++) { val = ((Component)list[i]).GetComponentInParent(); if ((Object)(object)val != (Object)null) { break; } } if ((Object)(object)val == (Object)null || (Object)(object)val.scroller == (Object)null) { return; } MenuButton[] componentsInChildren = ((Component)val.scroller).GetComponentsInChildren(true); foreach (MenuButton val2 in componentsInChildren) { if (Usable(val2) && !list.Contains(val2)) { list.Add(val2); } } } private List PageButtons(MenuManager mm, MenuPage page) { List list = ButtonsRef.Invoke(mm); List list2 = new List(); if (list == null) { return list2; } foreach (MenuButton item in list) { if (Usable(item) && (Object)(object)ParentPageRef.Invoke(item) == (Object)(object)page) { list2.Add(item); } } return list2; } private static bool Usable(MenuButton b) { if ((Object)(object)b != (Object)null && !DisabledRef.Invoke(b)) { return (Object)(object)b.rectTransformSelection != (Object)null; } return false; } private static bool IsActivePage(MenuPage p) { //IL_0017: 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_001a: Invalid comparison between Unknown and I4 //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 if ((Object)(object)p == (Object)null) { return true; } PageState val = PageStateRef.Invoke(p); if ((int)val != 3) { return (int)val != 2; } return false; } private static bool IsFocusableAdded(MenuPage p) { //IL_0017: 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_001a: Invalid comparison between Unknown and I4 //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 if ((Object)(object)p == (Object)null) { return false; } PageState val = PageStateRef.Invoke(p); if ((int)val != 2) { return (int)val != 5; } return false; } private static string Label(MenuButton b) { if ((Object)(object)b == (Object)null) { return ""; } object obj = ((ButtonTextField != null) ? ButtonTextField.GetValue(b) : null); if (obj != null) { if (s_textProp == null) { s_textProp = obj.GetType().GetProperty("text"); } if (s_textProp?.GetValue(obj) is string text && !string.IsNullOrEmpty(text)) { return text; } } return ((Object)((Component)b).gameObject).name; } private static Vector2 ScreenPos(MenuButton b) { //IL_0022: 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_0028: 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_0034: 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) Transform transform = ((Component)b).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val != (Object)null) { return RectPos(val); } Vector3 position = ((Component)b).transform.position; return new Vector2(position.x, position.y); } private static Vector2 RectPos(RectTransform rt) { //IL_0020: 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_0030: 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_0040: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rt == (Object)null) { return Vector2.zero; } rt.GetWorldCorners(s_corners); Vector3 val = (s_corners[0] + s_corners[2]) * 0.5f; return new Vector2(val.x, val.y); } private static MenuButton Topmost(List c) { return (from b in c orderby ScreenPos(b).y descending, ScreenPos(b).x select b).First(); } private MenuButton Reseed(List candidates) { if ((Object)(object)_focusPage != (Object)null && _lastByPage.TryGetValue(_focusPage, out var value) && (Object)(object)value != (Object)null && candidates.Contains(value)) { return value; } return Topmost(candidates); } private void HandleNavigation(Gamepad gp, List candidates, List hovers) { //IL_009f: 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) //IL_00af: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0110: 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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_035f: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Unknown result type (might be due to invalid IL or missing references) if (_navCooldown > 0f) { _navCooldown -= Time.deltaTime; } Vector2 val = new Vector2((gp.dpad.right.isPressed ? 1f : 0f) - (gp.dpad.left.isPressed ? 1f : 0f), (gp.dpad.up.isPressed ? 1f : 0f) - (gp.dpad.down.isPressed ? 1f : 0f)) + ((InputControl)(object)gp.leftStick).ReadValue(); if (((Vector2)(ref val)).magnitude < 0.4f) { _navCooldown = 0f; } else { if (_navCooldown > 0f) { return; } _navCooldown = 0.22f; Vector2 val2 = ((Mathf.Abs(val.x) > Mathf.Abs(val.y)) ? new Vector2(Mathf.Sign(val.x), 0f) : new Vector2(0f, Mathf.Sign(val.y))); if (val2.x > 0.5f && (Object)(object)_selectedHover != (Object)null) { MenuElementSaveFile componentInParent = ((Component)_selectedHover).GetComponentInParent(); MenuPageSaves val3 = (((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent).GetComponentInParent() : null); GameObject val4 = (((Object)(object)val3 != (Object)null) ? val3.saveFileInfoLoadButton : null); MenuButton val5 = (((Object)(object)val4 != (Object)null && val4.activeInHierarchy) ? val4.GetComponentInChildren() : null); if ((Object)(object)val5 != (Object)null && candidates.Contains(val5)) { _selected = val5; _selectedHover = null; SnapSelectionBoxUntil = Time.unscaledTime + 0.1f; if ((Object)(object)MenuManager.instance != (Object)null) { MenuManager.instance.MenuEffectHover(-1f, -1f); } return; } } Transform val6 = (((Object)(object)_selectedHover != (Object)null) ? ((Component)_selectedHover).transform : (((Object)(object)_selected != (Object)null) ? ((Component)_selected).transform : null)); if ((Object)(object)val6 == (Object)null) { return; } FillRect(val6, out var pos, out var min, out var max); int num = -1; List list = null; MenuScrollBox box = (((Object)(object)_selectedHover == (Object)null && (Object)(object)_selected != (Object)null) ? ((Component)_selected).GetComponentInParent() : null); if ((Object)(object)box != (Object)null) { list = BuildEntries(candidates.Where((MenuButton b) => (Object)(object)((Component)b).GetComponentInParent() == (Object)(object)box).ToList(), null); num = NearestInDirection(list, pos, min, max, val2); } if (num < 0) { list = BuildEntries(candidates, hovers); num = NearestInDirection(list, pos, min, max, val2); } if ((num < 0 && Mathf.Abs(val2.x) > 0.5f && TrySwitchPanel((!(val2.x < 0f)) ? 1 : (-1))) || num < 0) { return; } NavEntry navEntry = list[num]; if ((Object)(object)navEntry.Btn == (Object)(object)_selected && (Object)(object)navEntry.Hover == (Object)(object)_selectedHover) { return; } _selected = navEntry.Btn; _selectedHover = navEntry.Hover; if (Vector2.Distance(pos, navEntry.Pos) > 150f) { SnapSelectionBoxUntil = Time.unscaledTime + 0.1f; } if ((Object)(object)navEntry.Btn != (Object)null) { ScrollIntoView(navEntry.Btn); if ((Object)(object)MenuManager.instance != (Object)null) { MenuManager.instance.MenuEffectHover(-1f, -1f); } } } } private static NavEntry MakeEntry(MenuButton b, MenuElementHover h, Transform t) { NavEntry result = new NavEntry { Btn = b, Hover = h }; FillRect(t, out result.Pos, out result.Min, out result.Max); return result; } private static List BuildEntries(List buttons, List hovers) { List list = new List(buttons.Count + (hovers?.Count ?? 0)); foreach (MenuButton button in buttons) { list.Add(MakeEntry(button, null, ((Component)button).transform)); } if (hovers != null) { foreach (MenuElementHover hover in hovers) { list.Add(MakeEntry(null, hover, ((Component)hover).transform)); } } return list; } private static void FillRect(Transform t, out Vector2 pos, out Vector2 min, out Vector2 max) { //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_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_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: 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_0018: 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_0029: 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_0035: 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_0041: Unknown result type (might be due to invalid IL or missing references) RectTransform val = (RectTransform)(object)((t is RectTransform) ? t : null); if ((Object)(object)val == (Object)null) { Vector3 position = t.position; pos = new Vector2(position.x, position.y); min = pos; max = pos; } else { val.GetWorldCorners(s_corners); min = new Vector2(Mathf.Min(s_corners[0].x, s_corners[2].x), Mathf.Min(s_corners[0].y, s_corners[2].y)); max = new Vector2(Mathf.Max(s_corners[0].x, s_corners[2].x), Mathf.Max(s_corners[0].y, s_corners[2].y)); pos = (min + max) * 0.5f; } } private List HoverCandidates(MenuPage focus) { List list = new List(); if ((Object)(object)focus == (Object)null) { return list; } MenuElementHover[] array = Object.FindObjectsOfType(); foreach (MenuElementHover val in array) { if (!((Object)(object)val == (Object)null) && ((Behaviour)val).isActiveAndEnabled && !((Object)(object)((Component)val).GetComponentInParent() != (Object)(object)focus) && IsHoverActivatable(val)) { list.Add(val); } } return list; } private static bool IsHoverActivatable(MenuElementHover h) { if ((Object)(object)((Component)h).GetComponentInParent() != (Object)null) { return true; } if ((Object)(object)((Component)h).GetComponentInParent() != (Object)null) { return true; } MenuButtonArrow componentInParent = ((Component)h).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { CanvasGroup component = ((Component)componentInParent).GetComponent(); if (!((Object)(object)component == (Object)null)) { return component.alpha > 0.5f; } return true; } return false; } private void ActivateHover(MenuElementHover h) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)h == (Object)null) { return; } try { MenuElementServer componentInParent = ((Component)h).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { MenuButtonPopUp component = ((Component)componentInParent).GetComponent(); if (!((Object)(object)component == (Object)null)) { MenuManager.instance.MenuEffectClick((MenuClickEffectType)1, (MenuPage)null, -1f, -1f, false); MenuManager.instance.PagePopUpTwoOptions(component, component.headerText, component.localizedHeader, component.headerColor, component.bodyText, component.localizedBody, component.option1Text, component.localizedOption1, component.option2Text, component.localizedOption2, component.richText); Plugin.Log.LogDebug((object)"[Gamepad] Hover select server row"); } return; } MenuButtonArrow componentInParent2 = ((Component)h).GetComponentInParent(); if ((Object)(object)componentInParent2 != (Object)null) { MenuManager.instance.MenuEffectClick((MenuClickEffectType)1, (MenuPage)null, -1f, -1f, false); SpringVelocityRef.Invoke(componentInParent2.hoverSpring) += 50f; componentInParent2.onClick.Invoke(); Plugin.Log.LogDebug((object)"[Gamepad] Hover select page arrow"); return; } MenuElementSaveFile componentInParent3 = ((Component)h).GetComponentInParent(); if ((Object)(object)componentInParent3 != (Object)null) { MenuPageSaves componentInParent4 = ((Component)componentInParent3).GetComponentInParent(); if (!((Object)(object)componentInParent4 == (Object)null)) { MenuManager.instance.MenuEffectClick((MenuClickEffectType)1, (MenuPage)null, -1f, -1f, false); componentInParent4.SaveFileSelected(SaveFileNameRef.Invoke(componentInParent3), SaveFileBackupsRef.Invoke(componentInParent3)); Plugin.Log.LogDebug((object)"[Gamepad] Hover select save file"); } } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Gamepad] Hover select failed: {arg}"); } } private static void PickTopmost(List buttons, List hovers, out MenuButton btn, out MenuElementHover hover) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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) btn = null; hover = null; float num = float.MinValue; float num2 = float.MaxValue; foreach (MenuButton button in buttons) { Vector2 val = ScreenPos(button); if (val.y > num || (val.y == num && val.x < num2)) { num = val.y; num2 = val.x; btn = button; hover = null; } } if (hovers == null) { return; } foreach (MenuElementHover hover2 in hovers) { Transform transform = ((Component)hover2).transform; Vector2 val2 = RectPos((RectTransform)(object)((transform is RectTransform) ? transform : null)); if (val2.y > num || (val2.y == num && val2.x < num2)) { num = val2.y; num2 = val2.x; btn = null; hover = hover2; } } } private bool TrySwitchPanel(int sign) { MenuManager instance = MenuManager.instance; if ((Object)(object)instance == (Object)null) { return false; } MenuPage val = CurrentPageRef.Invoke(instance); MenuPage val2 = DefaultFocus(instance); if ((Object)(object)val2 == (Object)null || (Object)(object)val == (Object)null || (Object)(object)val2 == (Object)(object)val) { return false; } MenuPage val3 = ((sign >= 0) ? (((Object)(object)_focusPage != (Object)(object)val2) ? val2 : null) : (((Object)(object)_focusPage == (Object)(object)val2) ? val : null)); if ((Object)(object)val3 == (Object)null) { return false; } List list = PageButtons(instance, val3); if (list.Count == 0) { return false; } _focusOverride = val3; _focusPage = val3; _selected = Reseed(list); _selectedHover = null; SnapSelectionBoxUntil = Time.unscaledTime + 0.1f; ScrollIntoView(_selected); if ((Object)(object)MenuManager.instance != (Object)null) { MenuManager.instance.MenuEffectHover(-1f, -1f); } return true; } private static void ScrollIntoView(MenuButton b) { if ((Object)(object)b == (Object)null) { return; } MenuScrollBox componentInParent = ((Component)b).GetComponentInParent(); if (!((Object)(object)componentInParent == (Object)null) && !((Object)(object)componentInParent.scroller == (Object)null)) { Transform val = ((Component)b).transform; while ((Object)(object)val != (Object)null && (Object)(object)val.parent != (Object)(object)componentInParent.scroller) { val = val.parent; } RectTransform val2 = (RectTransform)(((object)((val is RectTransform) ? val : null)) ?? ((object)/*isinst with value type is only supported in some contexts*/)); componentInParent.ScrollToChild(val2, 0f); } } private static int NearestInDirection(List entries, Vector2 origin, Vector2 originMin, Vector2 originMax, Vector2 dir) { //IL_0000: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_009d: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_004a: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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) if (dir.y == 0f) { int num = -1; float num2 = float.MaxValue; for (int i = 0; i < entries.Count; i++) { Vector2 val = entries[i].Pos - origin; if (!(Mathf.Abs(val.y) > 12f)) { float num3 = val.x * dir.x; if (num3 > 0.5f && num3 < num2) { num2 = num3; num = i; } } } if (num >= 0) { return num; } } float minStep = ((dir.y != 0f) ? 12f : 0.5f); int num4 = BandPick(entries, origin, originMin, originMax, dir, minStep, PickMode.Beam); if (num4 < 0) { num4 = BandPick(entries, origin, originMin, originMax, dir, minStep, PickMode.Cone); } if (num4 < 0) { num4 = BandPick(entries, origin, originMin, originMax, dir, minStep, PickMode.Any); } return num4; } private static bool ModeAllows(PickMode mode, NavEntry e, Vector2 originMin, Vector2 originMax, Vector2 dir, float along, float perp) { //IL_0009: 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) //IL_004e: 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_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_0061: 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_0035: Unknown result type (might be due to invalid IL or missing references) switch (mode) { case PickMode.Beam: if (dir.y == 0f) { if (e.Max.y >= originMin.y) { return e.Min.y <= originMax.y; } return false; } if (e.Max.x >= originMin.x) { return e.Min.x <= originMax.x; } return false; case PickMode.Cone: return perp <= along; default: return true; } } private static int BandPick(List entries, Vector2 origin, Vector2 originMin, Vector2 originMax, Vector2 dir, float minStep, PickMode mode) { //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_0021: 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_0032: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_007a: 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_007c: 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_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0107: 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_0116: 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_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) float num = float.MaxValue; for (int i = 0; i < entries.Count; i++) { Vector2 val = entries[i].Pos - origin; float num2 = val.x * dir.x + val.y * dir.y; if (!(num2 <= minStep)) { float perp = Mathf.Abs(val.x * dir.y - val.y * dir.x); if (ModeAllows(mode, entries[i], originMin, originMax, dir, num2, perp) && num2 < num) { num = num2; } } } if (num == float.MaxValue) { return -1; } float num3 = num + 14f; int result = -1; float num4 = float.MaxValue; for (int j = 0; j < entries.Count; j++) { Vector2 val2 = entries[j].Pos - origin; float num5 = val2.x * dir.x + val2.y * dir.y; if (num5 <= minStep || num5 > num3) { continue; } float num6 = Mathf.Abs(val2.x * dir.y - val2.y * dir.x); if (ModeAllows(mode, entries[j], originMin, originMax, dir, num5, num6)) { float num7 = num6 * 10000f + num5; if (num7 < num4) { num4 = num7; result = j; } } } return result; } private static void Select(MenuButton b) { if ((Object)(object)b == (Object)null) { return; } try { OnSelectMethod.Invoke(b, null); Plugin.Log.LogDebug((object)("[Gamepad] Menu select '" + Label(b) + "'")); } catch (Exception arg) { Plugin.Log.LogError((object)$"[Gamepad] Menu select failed: {arg}"); } } private void Back(List candidates) { //IL_00ac: 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_00c8: Unknown result type (might be due to invalid IL or missing references) MenuManager instance = MenuManager.instance; if ((Object)(object)instance != (Object)null) { List list = AddedPagesRef.Invoke(instance); if (list != null && list.Any((MenuPage p) => IsFocusableAdded(p))) { instance.PageCloseAllAddedOnTop(); ResetRepoConfigGuard(); Plugin.Log.LogDebug((object)"[Gamepad] B -> close added-on-top page (back one level)."); return; } } MenuButton val = ((IEnumerable)candidates).FirstOrDefault((Func)((MenuButton b) => IsBackLabel(Label(b)))); if ((Object)(object)val != (Object)null) { Select(val); return; } Keyboard current = Keyboard.current; if (current != null) { InputSystem.QueueStateEvent((InputDevice)(object)current, new KeyboardState((Key[])(object)new Key[1] { (Key)60 }), -1.0); InputSystem.QueueStateEvent((InputDevice)(object)current, default(KeyboardState), -1.0); Plugin.Log.LogDebug((object)"[Gamepad] B -> Escape (no labeled Back / added page)."); } } private static void ResetRepoConfigGuard() { if (!s_repoLookupDone) { s_repoLookupDone = true; Type type = AccessTools.TypeByName("REPOConfig.ConfigMenu"); if (type != null) { s_repoLastClicked = AccessTools.Field(type, "lastClickedModButton"); } } s_repoLastClicked?.SetValue(null, null); } private static bool IsBackLabel(string s) { if (string.IsNullOrEmpty(s)) { return false; } s = s.ToLowerInvariant(); if (!s.Contains("back") && !s.Contains("cancel") && !s.Contains("close") && !s.Contains("return")) { return s.Contains("resume"); } return true; } private void OnGUI() { //IL_00bb: 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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0113: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown if (Plugin.Enabled.Value && Gamepad.current != null && MenuOpen(out var _) && ControllerActive) { if (_style == null) { _style = new GUIStyle(GUI.skin.label) { fontSize = 18, fontStyle = (FontStyle)1 }; } ControllerDetect.Kind current = ControllerDetect.Current; string text = "D-Pad: Move " + ButtonNames.Of(ButtonNames.Control.South, current) + ": Select " + ButtonNames.Of(ButtonNames.Control.East, current) + ": Back"; Rect rect = default(Rect); ((Rect)(ref rect))..ctor(20f, (float)(Screen.height - 40), 700f, 30f); _style.normal.textColor = Color.black; ControllerGlyphs.DrawLabel(new Rect(((Rect)(ref rect)).x + 1f, ((Rect)(ref rect)).y + 1f, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), text, _style); _style.normal.textColor = Color.white; ControllerGlyphs.DrawLabel(rect, text, _style); } } } [HarmonyPatch(typeof(SemiFunc), "UIMouseHover")] internal static class HoverElementForcePatch { [HarmonyPostfix] private static void Postfix(RectTransform rectTransform, ref bool __result) { if (MenuNavigator.ControllerActive) { RectTransform selectedHoverRect = MenuNavigator.SelectedHoverRect; __result = (Object)(object)selectedHoverRect != (Object)null && rectTransform == selectedHoverRect; } } } [HarmonyPatch(typeof(SemiFunc), "MenuSelectionBoxTargetSet")] internal static class SelectionBoxSnapPatch { private static readonly FieldRef PageBoxRef = AccessTools.FieldRefAccess("selectionBox"); private static readonly FieldRef SelInScrollBoxRef = AccessTools.FieldRefAccess("isInScrollBox"); private static readonly FieldRef SelScrollBoxRef = AccessTools.FieldRefAccess("menuScrollBox"); private static readonly FieldRef TargetPosRef = AccessTools.FieldRefAccess("targetPosition"); private static readonly FieldRef TargetScaleRef = AccessTools.FieldRefAccess("targetScale"); private static readonly FieldRef CurrentScaleRef = AccessTools.FieldRefAccess("currentScale"); private static readonly FieldRef BoxRectRef = AccessTools.FieldRefAccess("rectTransform"); [HarmonyPostfix] private static void Postfix(MenuPage parentPage, RectTransform rectTransform) { //IL_00a6: 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_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) if (!MenuNavigator.ControllerActive || Time.unscaledTime > MenuNavigator.SnapSelectionBoxUntil || (Object)(object)parentPage == (Object)null || (Object)(object)rectTransform == (Object)null) { return; } MenuSelectionBox val = PageBoxRef.Invoke(parentPage); MenuSelectableElement component = ((Component)rectTransform).GetComponent(); if ((Object)(object)component != (Object)null && SelInScrollBoxRef.Invoke(component) && (Object)(object)SelScrollBoxRef.Invoke(component) != (Object)null) { val = SelScrollBoxRef.Invoke(component).menuSelectionBox; } if (!((Object)(object)val == (Object)null)) { RectTransform val2 = BoxRectRef.Invoke(val); if (!((Object)(object)val2 == (Object)null)) { ((Transform)val2).localPosition = TargetPosRef.Invoke(val); CurrentScaleRef.Invoke(val) = TargetScaleRef.Invoke(val) / 100f; MenuNavigator.SnapSelectionBoxUntil = 0f; } } } } [HarmonyPatch(typeof(MenuScrollBox), "Update")] internal static class MenuScrollBoxScrollPatch { private static readonly FieldRef ActiveRef = AccessTools.FieldRefAccess("scrollBoxActive"); private static readonly FieldRef HandleTargetRef = AccessTools.FieldRefAccess("scrollHandleTargetPosition"); private static readonly FieldRef ScrollerStartRef = AccessTools.FieldRefAccess("scrollerStartPosition"); private static readonly FieldRef ScrollerEndRef = AccessTools.FieldRefAccess("scrollerEndPosition"); private static readonly FieldRef ScrollAmountRef = AccessTools.FieldRefAccess("scrollAmount"); private static void Postfix(MenuScrollBox __instance) { //IL_0092: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) if (!MenuNavigator.ControllerActive) { return; } MenuButton selected = MenuNavigator.Selected; if (!((Object)(object)selected == (Object)null) && !((Object)(object)((Component)selected).GetComponentInParent() != (Object)(object)__instance) && !ActiveRef.Invoke(__instance) && !((Object)(object)__instance.scrollBar == (Object)null) && __instance.scrollBar.activeSelf) { RectTransform scrollHandle = __instance.scrollHandle; RectTransform scrollBarBackground = __instance.scrollBarBackground; RectTransform scroller = __instance.scroller; if (!((Object)(object)scrollHandle == (Object)null) && !((Object)(object)scrollBarBackground == (Object)null) && !((Object)(object)scroller == (Object)null)) { float num = HandleTargetRef.Invoke(__instance); float num2 = Mathf.Lerp(((Transform)scrollHandle).localPosition.y, num, Time.deltaTime * 20f); ((Transform)scrollHandle).localPosition = new Vector3(((Transform)scrollHandle).localPosition.x, num2, ((Transform)scrollHandle).localPosition.z); float num3 = scrollHandle.sizeDelta.y / 2f; Rect rect = scrollBarBackground.rect; float num4 = ((Rect)(ref rect)).height - scrollHandle.sizeDelta.y / 2f; float num5 = Mathf.Clamp01(Mathf.InverseLerp(num3, num4, ((Transform)scrollHandle).localPosition.y)); ScrollAmountRef.Invoke(__instance) = num5; ((Transform)scroller).localPosition = new Vector3(((Transform)scroller).localPosition.x, Mathf.Lerp(ScrollerStartRef.Invoke(__instance), ScrollerEndRef.Invoke(__instance), num5), ((Transform)scroller).localPosition.z); } } } } internal class PadKeyboardCore { private const float RepeatDelay = 0.4f; private const float RepeatRate = 0.12f; private static readonly string[] CharRows = new string[4] { "1234567890", "QWERTYUIOP", "ASDFGHJKL'", "ZXCVBNM,.?" }; private const int SpecialRow = 4; private static readonly string[][] KeyLabels = BuildKeyLabels(); internal Action OnChar; internal Action OnConfirm; internal Action OnClose; private readonly bool _hasSpace; private readonly string[] _specialKeys; private readonly string _hideLabel; private int _row; private int _col; private int _heldX; private int _heldY; private float _repeatTimer; private GUIStyle _key; private GUIStyle _keyHover; private GUIStyle _hintL; private GUIStyle _hintC; private GUIStyle _hintR; private float _styleScale = -1f; private string _hintLeft; private string _hintCenter; private string _hintRight; private ControllerDetect.Kind _hintsKind; private bool _hintsBuilt; internal float LastPanelTop { get; private set; } internal PadKeyboardCore(bool hasSpace, string confirmLabel, string hideLabel = null) { _hasSpace = hasSpace; _hideLabel = hideLabel; List list = new List { "!" }; if (hasSpace) { list.Add("SPACE"); } if (hideLabel != null) { list.Add(hideLabel); } list.Add(confirmLabel); _specialKeys = list.ToArray(); } private static string[][] BuildKeyLabels() { string[][] array = new string[CharRows.Length][]; for (int i = 0; i < CharRows.Length; i++) { array[i] = new string[CharRows[i].Length]; for (int j = 0; j < CharRows[i].Length; j++) { array[i][j] = CharRows[i][j].ToString(); } } return array; } internal void Reset() { _row = 1; _col = 0; _heldX = 0; _heldY = 0; _repeatTimer = 0f; _hintsBuilt = false; } internal void HandleInput(Gamepad gp) { HandleNavigation(gp); if (gp.buttonSouth.wasPressedThisFrame) { PressHovered(); } if (_hasSpace && gp.buttonWest.wasPressedThisFrame) { OnChar?.Invoke(" "); } if (gp.startButton.wasPressedThisFrame) { OnConfirm?.Invoke(); } } private void PressHovered() { if (_row == 4) { string text = _specialKeys[_col]; if (text == "SPACE") { OnChar?.Invoke(" "); } else if (text == "!") { OnChar?.Invoke("!"); } else if (_hideLabel != null && text == _hideLabel) { OnClose?.Invoke(); } else { OnConfirm?.Invoke(); } } else { OnChar?.Invoke(char.ToLowerInvariant(CharRows[_row][_col]).ToString()); } } private void HandleNavigation(Gamepad gp) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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) Vector2 val = ((InputControl)(object)gp.leftStick).ReadValue(); float num = Mathf.Max(Plugin.StickDeadzone.Value, 0.35f); int num2 = ((Mathf.Abs(val.x) > num) ? Math.Sign(val.x) : 0); int num3 = ((Mathf.Abs(val.y) > num) ? (-Math.Sign(val.y)) : 0); int num4 = (gp.dpad.left.isPressed ? (-1) : 0) + (gp.dpad.right.isPressed ? 1 : 0); int num5 = (gp.dpad.up.isPressed ? (-1) : 0) + (gp.dpad.down.isPressed ? 1 : 0); if (num4 == 0) { num4 = num2; } if (num5 == 0) { num5 = num3; } if (num4 == 0 && num5 == 0) { _heldX = 0; _heldY = 0; return; } if (num4 != _heldX || num5 != _heldY) { _heldX = num4; _heldY = num5; _repeatTimer = 0.4f; MoveCursor(num4, num5); return; } _repeatTimer -= Time.unscaledDeltaTime; if (_repeatTimer <= 0f) { _repeatTimer = 0.12f; MoveCursor(num4, num5); } } private void MoveCursor(int dx, int dy) { if (dy != 0) { int num = ColsIn(_row); float num2 = ((num > 1) ? ((float)_col / (float)(num - 1)) : 0f); _row = (_row + dy + 5) % 5; int num3 = ColsIn(_row); _col = Mathf.Clamp(Mathf.RoundToInt(num2 * (float)(num3 - 1)), 0, num3 - 1); } if (dx != 0) { int num4 = ColsIn(_row); _col = (_col + dx + num4) % num4; } } private int ColsIn(int row) { if (row != 4) { return CharRows[row].Length; } return _specialKeys.Length; } internal void Draw(float s, float bottomOffset) { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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_0169: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: 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) EnsureStyles(s); float num = 34f * s; float num2 = 4f * s; float num3 = 10f * s; float num4 = 10f * num + 9f * num2; float num5 = num4 + 2f * num3; float num6 = 22f * s; float num7 = 5f * (num + num2) - num2 + 2f * num3 + num6; float num8 = ((float)Screen.width - num5) / 2f; float num9 = (LastPanelTop = (float)Screen.height - num7 - bottomOffset); GUI.color = new Color(0f, 0f, 0f, 0.55f); GUI.DrawTexture(new Rect(num8, num9, num5, num7), (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; for (int i = 0; i < 4; i++) { for (int j = 0; j < CharRows[i].Length; j++) { DrawKey(new Rect(num8 + num3 + (float)j * (num + num2), num9 + num3 + (float)i * (num + num2), num, num), KeyLabels[i][j], i == _row && j == _col); } } float num11 = num9 + num3 + 4f * (num + num2); int num12 = _specialKeys.Length; float num13 = (num4 - num - (float)(num12 - 1) * num2) / (float)(num12 - 1); DrawKey(new Rect(num8 + num3, num11, num, num), "!", _row == 4 && _col == 0); for (int k = 1; k < num12; k++) { DrawKey(new Rect(num8 + num3 + num + num2 + (float)(k - 1) * (num13 + num2), num11, num13, num), _specialKeys[k], _row == 4 && _col == k); } ControllerDetect.Kind current = ControllerDetect.Current; if (!_hintsBuilt || current != _hintsKind) { _hintsBuilt = true; _hintsKind = current; _hintLeft = ButtonNames.Of(ButtonNames.Control.South, current) + " type"; _hintCenter = (_hasSpace ? (ButtonNames.Of(ButtonNames.Control.West, current) + " space") : ""); _hintRight = ButtonNames.Of(ButtonNames.Control.East, current) + " backspace"; } Rect val = default(Rect); ((Rect)(ref val))..ctor(num8 + num3, num11 + num + num2, num4, num6); GUI.Label(val, _hintLeft, _hintL); if (_hintCenter.Length != 0) { GUI.Label(val, _hintCenter, _hintC); } GUI.Label(val, _hintRight, _hintR); } private void DrawKey(Rect rect, string label, bool hovered) { //IL_0032: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) GUI.color = (hovered ? new Color(0.3f, 0.26f, 0.08f, 0.95f) : new Color(0.1f, 0.1f, 0.1f, 0.9f)); GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; GUI.Label(rect, label, hovered ? _keyHover : _key); } private void EnsureStyles(float scale) { //IL_0029: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0053: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_008f: 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_00a9: 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_00c3: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_0106: 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_0117: Expected O, but got Unknown if (_key == null || !Mathf.Approximately(_styleScale, scale)) { _styleScale = scale; _key = new GUIStyle(GUI.skin.label) { fontSize = (int)(15f * scale), alignment = (TextAnchor)4 }; _key.normal.textColor = Color.white; _keyHover = new GUIStyle(_key) { fontStyle = (FontStyle)1 }; _keyHover.normal.textColor = new Color(1f, 0.85f, 0.3f); _hintL = new GUIStyle(GUI.skin.label) { fontSize = (int)(12f * scale), alignment = (TextAnchor)3 }; _hintL.normal.textColor = new Color(0.75f, 0.77f, 0.85f); _hintC = new GUIStyle(_hintL) { alignment = (TextAnchor)4 }; _hintR = new GUIStyle(_hintL) { alignment = (TextAnchor)5 }; } } } [BepInPlugin("com.pogwas.nativecontroller", "Native Controller", "0.6.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.pogwas.nativecontroller"; public const string PluginName = "Native Controller"; public const string PluginVersion = "0.6.0"; internal static Plugin Instance; internal static ManualLogSource Log; internal static ConfigEntry Enabled; internal static ConfigEntry LookSpeedX; internal static ConfigEntry LookSpeedY; internal static ConfigEntry InvertY; internal static ConfigEntry InvertX; internal static ConfigEntry StickDeadzone; internal static ConfigEntry MenuCursorSpeed; internal static ConfigEntry EmoteWheelEnabled; internal static ConfigEntry EmoteZoomOut; internal static ConfigEntry EmoteCameraLower; internal static ConfigEntry EmoteDurationSeconds; internal static ConfigEntry PromptsEnabled; internal static ConfigEntry ControllerKeyTags; internal static ConfigEntry InventoryArrows; internal static ConfigEntry SprintToggle; internal static ConfigEntry GrabToggle; internal static ConfigEntry CrouchToggle; internal static ConfigEntry GlyphStyle; internal static ConfigEntry PushToTalkButton; internal static ConfigEntry ChatKeyboardEnabled; internal static ConfigEntry ChatScale; internal static ConfigEntry ChatHistoryRecallEnabled; internal static ConfigEntry MenuKeyboardEnabled; internal static ConfigEntry ChatLogEnabled; internal static ConfigEntry ChatLogVisibleSeconds; internal static ConfigEntry ChatLogMaxVisible; internal static ConfigEntry VoiceIndicatorEnabled; internal static ConfigEntry HideMouseCursorOnPad; internal static ConfigEntry AimAssistEnabled; internal static ConfigEntry AimAssistItems; internal static ConfigEntry AimAssistEnemies; internal static ConfigEntry AimAssistGain; internal static ConfigEntry AimAssistMaxFraction; internal static ConfigEntry AimAssistMaxDegPerFrame; internal static ConfigEntry AimAssistIdleDrift; internal static ConfigEntry AimAssistActiveThreshold; internal static ConfigEntry AimAssistDeadZone; internal static ConfigEntry AimAssistItemRange; internal static ConfigEntry AimAssistEnemyRange; internal static ConfigEntry AimAssistMaxAngle; private Harmony _harmony; private static GameObject _menuNavGO; private static GameObject _overlayGO; private static GameObject _aimAssistGO; private static GameObject _emoteWheelGO; private static GameObject _grabPromptsGO; private static GameObject _chatKeyboardGO; private static GameObject _menuKeyboardGO; private static GameObject _chatLogGO; private static GameObject _voiceIndicatorGO; private void Awake() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Expected O, but got Unknown //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Expected O, but got Unknown //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Expected O, but got Unknown //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Expected O, but got Unknown //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Expected O, but got Unknown //IL_03e2: Unknown result type (might be due to invalid IL or missing references) //IL_03ec: Expected O, but got Unknown //IL_047f: Unknown result type (might be due to invalid IL or missing references) //IL_0489: Expected O, but got Unknown //IL_04b1: Unknown result type (might be due to invalid IL or missing references) //IL_04bb: Expected O, but got Unknown //IL_056e: Unknown result type (might be due to invalid IL or missing references) //IL_0578: Expected O, but got Unknown //IL_05ab: Unknown result type (might be due to invalid IL or missing references) //IL_05b5: Expected O, but got Unknown //IL_05e8: Unknown result type (might be due to invalid IL or missing references) //IL_05f2: Expected O, but got Unknown //IL_0625: Unknown result type (might be due to invalid IL or missing references) //IL_062f: Expected O, but got Unknown //IL_0662: Unknown result type (might be due to invalid IL or missing references) //IL_066c: Expected O, but got Unknown //IL_069f: Unknown result type (might be due to invalid IL or missing references) //IL_06a9: Expected O, but got Unknown //IL_06dc: Unknown result type (might be due to invalid IL or missing references) //IL_06e6: Expected O, but got Unknown //IL_0719: Unknown result type (might be due to invalid IL or missing references) //IL_0723: Expected O, but got Unknown //IL_0756: Unknown result type (might be due to invalid IL or missing references) //IL_0760: Expected O, but got Unknown //IL_0770: Unknown result type (might be due to invalid IL or missing references) //IL_077a: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"Native Controller v0.6.0 loading..."); Enabled = ((BaseUnityPlugin)this).Config.Bind("Gamepad", "Enabled", true, "Master toggle for gamepad support. When off, the controller does nothing and keyboard/mouse are unaffected."); LookSpeedX = ((BaseUnityPlugin)this).Config.Bind("Gamepad", "LookSpeedX", 1f, new ConfigDescription("Right-stick horizontal camera speed.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 20f), Array.Empty())); LookSpeedY = ((BaseUnityPlugin)this).Config.Bind("Gamepad", "LookSpeedY", 1f, new ConfigDescription("Right-stick vertical camera speed.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 20f), Array.Empty())); InvertY = ((BaseUnityPlugin)this).Config.Bind("Gamepad", "InvertY", false, "Invert right-stick vertical look."); InvertX = ((BaseUnityPlugin)this).Config.Bind("Gamepad", "InvertX", false, "Invert right-stick horizontal look."); StickDeadzone = ((BaseUnityPlugin)this).Config.Bind("Gamepad", "StickDeadzone", 0.15f, new ConfigDescription("Right-stick deadzone (ignore small movements).", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 0.6f), Array.Empty())); MenuCursorSpeed = ((BaseUnityPlugin)this).Config.Bind("Gamepad", "MenuCursorSpeed", 12f, new ConfigDescription("Left-stick cursor speed when navigating menus.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 50f), Array.Empty())); EmoteWheelEnabled = ((BaseUnityPlugin)this).Config.Bind("Emote Wheel", "Enabled", true, "Hold D-pad Down in-game to open an emote wheel (right stick to pick, release to toggle the expression on/off)."); EmoteZoomOut = ((BaseUnityPlugin)this).Config.Bind("Emote Wheel", "PreviewZoomOut", 0.5f, new ConfigDescription("How far the face-preview camera pulls back while the wheel is open (metres). Tune live in the in-game mod settings until the whole face is visible.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 3f), Array.Empty())); EmoteCameraLower = ((BaseUnityPlugin)this).Config.Bind("Emote Wheel", "PreviewCameraLower", 0.25f, new ConfigDescription("How far the face-preview camera drops while the wheel is open (metres) — raises the head in the picture. Tune live alongside PreviewZoomOut.", (AcceptableValueBase)(object)new AcceptableValueRange(-1f, 1f), Array.Empty())); EmoteDurationSeconds = ((BaseUnityPlugin)this).Config.Bind("Emote Wheel", "EmoteDurationSeconds", 5f, new ConfigDescription("How long a picked emote stays on your face before returning to normal. 0 = it stays until you pick it again on the wheel.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 30f), Array.Empty())); PromptsEnabled = ((BaseUnityPlugin)this).Config.Bind("Prompts", "Enabled", true, "Show controller prompts near the crosshair (Grab when aiming at a grabbable, Let go / Rotate while holding, Climb when tumbling at a wall). Only shown while the controller is the active input."); ControllerKeyTags = ((BaseUnityPlugin)this).Config.Bind("Prompts", "ControllerKeyTags", true, "Show controller buttons inside the game's own key hints (e.g. SHOTGUN [X] instead of [E]) while the controller is the active input."); InventoryArrows = ((BaseUnityPlugin)this).Config.Bind("Prompts", "InventoryArrows", true, "Show which D-pad arrow equips which inventory slot (â†\u0090 ↑ → above the three slots). Only while the controller is the active input."); SprintToggle = ((BaseUnityPlugin)this).Config.Bind("Gamepad", "ToggleSprint", true, "Press Sprint (L3) once to keep sprinting; it stops when stamina runs out, you stop moving, or you press it again. Applies while a gamepad is connected (also affects keyboard Sprint)."); GrabToggle = ((BaseUnityPlugin)this).Config.Bind("Gamepad", "ToggleGrab", true, "Press Grab (RT) once to keep holding a grabbed object; press again to let go. Auto-releases if the grab breaks. Applies while a gamepad is connected (also affects keyboard/mouse Grab)."); CrouchToggle = ((BaseUnityPlugin)this).Config.Bind("Gamepad", "ToggleCrouch", true, "Press Crouch (R3) once to stay crouched; press again to stand. Applies while a gamepad is connected (also affects keyboard Crouch)."); GlyphStyle = ((BaseUnityPlugin)this).Config.Bind("Gamepad", "GlyphStyle", ControllerDetect.Style.Auto, "Which controller's button names/glyphs to show. Auto = detect from the connected pad."); PushToTalkButton = ((BaseUnityPlugin)this).Config.Bind("Gamepad", "PushToTalkButton", PadButton.None, "Hold this pad button to talk when the game's 'Push to Talk' audio setting is ON (works exactly like holding V). The chosen button KEEPS its normal function too — pick a conflict you can live with. None = off."); PushToTalkButton.SettingChanged += delegate { GamepadBindingsPatch.RebindPushToTalk(); }; HideMouseCursorOnPad = ((BaseUnityPlugin)this).Config.Bind("Gamepad", "HideMouseCursor", true, "Hide the game's menu mouse pointer while the controller is the active input. It comes back the moment you move the mouse."); ChatKeyboardEnabled = ((BaseUnityPlugin)this).Config.Bind("Chat Keyboard", "Enabled", true, "Show an on-screen keyboard when you open chat with the controller (Back/View). D-pad / left stick moves, A types, B deletes, X = space, Start sends, Back/View closes. Chat opened from the keyboard never shows it."); ChatScale = ((BaseUnityPlugin)this).Config.Bind("Chat", "Scale", 1f, new ConfigDescription("One size knob for all of this mod's chat UI: the on-screen chat/menu keyboards and the chat history box.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 2f), Array.Empty())); ChatHistoryRecallEnabled = ((BaseUnityPlugin)this).Config.Bind("Chat Keyboard", "HistoryRecallEnabled", true, "Flick the right stick up/down while the on-screen chat keyboard is open to recall recently sent messages (up = older, down = newer), like vanilla's Up/Down arrow keys."); MenuKeyboardEnabled = ((BaseUnityPlugin)this).Config.Bind("Menu Keyboard", "Enabled", true, "Show an on-screen keyboard on the game's menu text fields (lobby name, save rename, server search, lobby password) while the controller is the active input. D-pad / left stick moves, A types, B deletes, X = space, Start confirms, Back/View hides it. Panel size follows [Chat] Scale."); ChatLogEnabled = ((BaseUnityPlugin)this).Config.Bind("Chat Log", "Enabled", true, "Show a chat box of recent messages (everyone's, with names, newest at the bottom) in the bottom-left corner, like a regular multiplayer chat. Vanilla has no chat log at all."); ChatLogVisibleSeconds = ((BaseUnityPlugin)this).Config.Bind("Chat Log", "VisibleSeconds", 6f, new ConfigDescription("How long the chat box stays on screen after a message arrives (fades out at the end). 0 = only visible while chat is open.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 30f), Array.Empty())); ChatLogMaxVisible = ((BaseUnityPlugin)this).Config.Bind("Chat Log", "MaxVisible", 8, new ConfigDescription("Maximum chat lines shown.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 15), Array.Empty())); VoiceIndicatorEnabled = ((BaseUnityPlugin)this).Config.Bind("Voice Indicator", "Enabled", true, "When the game's Push to Talk setting is ON, show the muted-mic icon (at its usual spot) while your mic is COLD - i.e. while you are NOT holding push-to-talk. Holding the talk button clears it: icon = silent, empty = live. Works even without a microphone. Vanilla gives no push-to-talk feedback at all."); AimAssistEnabled = ((BaseUnityPlugin)this).Config.Bind("Aim Assist", "Enabled", true, "Master toggle for aim assist (gently nudges your view toward items, and toward enemies when a weapon/staff is held)."); AimAssistItems = ((BaseUnityPlugin)this).Config.Bind("Aim Assist", "AssistItems", true, "Pull your view slightly toward a nearby grabbable item near your crosshair."); AimAssistEnemies = ((BaseUnityPlugin)this).Config.Bind("Aim Assist", "AssistEnemies", true, "Pull your view slightly toward an enemy when you hold a weapon or magic staff and aim near one."); AimAssistGain = ((BaseUnityPlugin)this).Config.Bind("Aim Assist", "Gain", 0.07f, new ConfigDescription("Fraction of the remaining angle the nudge closes per frame (before clamping). Higher = quicker settle. Kept tiny on purpose.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 0.5f), Array.Empty())); AimAssistMaxFraction = ((BaseUnityPlugin)this).Config.Bind("Aim Assist", "MaxFraction", 0.3f, new ConfigDescription("While you are turning, the assist is capped at this fraction of YOUR OWN look this frame. Below 1.0 it can never out-turn you — this is the no-lock guarantee.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 0.9f), Array.Empty())); AimAssistMaxDegPerFrame = ((BaseUnityPlugin)this).Config.Bind("Aim Assist", "MaxDegPerFrame", 0.5f, new ConfigDescription("Absolute ceiling (degrees/frame) on the nudge, so a fast flick is never visibly curved.", (AcceptableValueBase)(object)new AcceptableValueRange(0.05f, 3f), Array.Empty())); AimAssistIdleDrift = ((BaseUnityPlugin)this).Config.Bind("Aim Assist", "IdleDrift", 0.1f, new ConfigDescription("Gentle drift (degrees/frame) toward the target ONLY when you are not moving the view; faded near the target so a parked camera never fully homes.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 0.5f), Array.Empty())); AimAssistActiveThreshold = ((BaseUnityPlugin)this).Config.Bind("Aim Assist", "ActiveThreshold", 0.05f, new ConfigDescription("Per-frame look (degrees) above which you count as 'turning' (uses the MaxFraction cap) vs 'stopped' (uses IdleDrift).", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); AimAssistDeadZone = ((BaseUnityPlugin)this).Config.Bind("Aim Assist", "DeadZone", 1.5f, new ConfigDescription("Inside this angle (degrees) of the target the assist does nothing — removes the hard settle/snap and lets your own aim finish the last bit.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 8f), Array.Empty())); AimAssistItemRange = ((BaseUnityPlugin)this).Config.Bind("Aim Assist", "ItemRange", 5f, new ConfigDescription("Max distance (metres) to assist toward an item.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 15f), Array.Empty())); AimAssistEnemyRange = ((BaseUnityPlugin)this).Config.Bind("Aim Assist", "EnemyRange", 25f, new ConfigDescription("Max distance (metres) to assist toward an enemy.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 60f), Array.Empty())); AimAssistMaxAngle = ((BaseUnityPlugin)this).Config.Bind("Aim Assist", "MaxAngle", 12f, new ConfigDescription("Cone (degrees from your crosshair) a target must be within to be assisted.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 45f), Array.Empty())); ControllerDetect.Init(); _harmony = new Harmony("com.pogwas.nativecontroller"); _harmony.PatchAll(); if (Chainloader.PluginInfos.ContainsKey("nickklmao.menulib")) { SettingsMenuEntry.Register(); Log.LogInfo((object)"[Gamepad] MenuLib detected — added Controller Layout to the Settings menu."); } SceneManager.sceneLoaded += OnSceneLoaded; Log.LogInfo((object)"Native Controller loaded."); } private static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Expected O, but got Unknown //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Expected O, but got Unknown //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Expected O, but got Unknown //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Expected O, but got Unknown if ((Object)(object)_menuNavGO == (Object)null) { _menuNavGO = new GameObject("NativeController.MenuNav", new Type[1] { typeof(MenuNavigator) }); Object.DontDestroyOnLoad((Object)(object)_menuNavGO); Log.LogDebug((object)"[Gamepad] MenuNavigator (re)created."); } if ((Object)(object)_overlayGO == (Object)null) { _overlayGO = new GameObject("NativeController.LayoutOverlay", new Type[1] { typeof(ControllerLayoutOverlay) }); Object.DontDestroyOnLoad((Object)(object)_overlayGO); Log.LogDebug((object)"[Gamepad] ControllerLayoutOverlay (re)created."); } if ((Object)(object)_aimAssistGO == (Object)null) { _aimAssistGO = new GameObject("NativeController.AimAssist", new Type[1] { typeof(AimAssist) }); Object.DontDestroyOnLoad((Object)(object)_aimAssistGO); Log.LogDebug((object)"[Gamepad] AimAssist (re)created."); } if ((Object)(object)_emoteWheelGO == (Object)null) { _emoteWheelGO = new GameObject("NativeController.EmoteWheel", new Type[1] { typeof(EmoteWheel) }); Object.DontDestroyOnLoad((Object)(object)_emoteWheelGO); Log.LogDebug((object)"[Gamepad] EmoteWheel (re)created."); } if ((Object)(object)_grabPromptsGO == (Object)null) { _grabPromptsGO = new GameObject("NativeController.GrabPrompts", new Type[1] { typeof(GrabPromptOverlay) }); Object.DontDestroyOnLoad((Object)(object)_grabPromptsGO); Log.LogDebug((object)"[Gamepad] GrabPromptOverlay (re)created."); } if ((Object)(object)_chatKeyboardGO == (Object)null) { _chatKeyboardGO = new GameObject("NativeController.ChatKeyboard", new Type[1] { typeof(ChatKeyboard) }); Object.DontDestroyOnLoad((Object)(object)_chatKeyboardGO); Log.LogDebug((object)"[Gamepad] ChatKeyboard (re)created."); } if ((Object)(object)_menuKeyboardGO == (Object)null) { _menuKeyboardGO = new GameObject("NativeController.MenuKeyboard", new Type[1] { typeof(MenuKeyboard) }); Object.DontDestroyOnLoad((Object)(object)_menuKeyboardGO); Log.LogDebug((object)"[Gamepad] MenuKeyboard (re)created."); } if ((Object)(object)_chatLogGO == (Object)null) { _chatLogGO = new GameObject("NativeController.ChatLog", new Type[1] { typeof(ChatLog) }); Object.DontDestroyOnLoad((Object)(object)_chatLogGO); Log.LogDebug((object)"[Gamepad] ChatLog (re)created."); } if ((Object)(object)_voiceIndicatorGO == (Object)null) { _voiceIndicatorGO = new GameObject("NativeController.VoiceIndicator", new Type[1] { typeof(VoiceIndicator) }); Object.DontDestroyOnLoad((Object)(object)_voiceIndicatorGO); Log.LogDebug((object)"[Gamepad] VoiceIndicator (re)created."); } EmoteWheel.ResetState(); ChatKeyboard.ResetState(); MenuKeyboard.ResetState(); VoiceIndicator.ResetState(); ControllerDetect.ResetLevelTouch(); } } [HarmonyPatch(typeof(InputManager), "KeyPullAndPush")] internal static class PushPullPatch { [HarmonyPostfix] public static void Postfix(ref float __result) { if (!Plugin.Enabled.Value) { return; } Gamepad current = Gamepad.current; if (current != null) { if (current.rightShoulder.isPressed) { __result = 1f; } else if (current.leftShoulder.isPressed) { __result = -1f; } } } } internal static class SettingsMenuEntry { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static BuilderDelegate <>9__0_0; internal void b__0_0(Transform parent) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (ControllerDetect.Current != ControllerDetect.Kind.None) { MenuAPI.CreateREPOButton("Controller Layout", (Action)ControllerLayoutOverlay.Toggle, parent, new Vector2(180f, 30f)); } } } internal static void Register() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown object obj = <>c.<>9__0_0; if (obj == null) { BuilderDelegate val = delegate(Transform parent) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (ControllerDetect.Current != ControllerDetect.Kind.None) { MenuAPI.CreateREPOButton("Controller Layout", (Action)ControllerLayoutOverlay.Toggle, parent, new Vector2(180f, 30f)); } }; <>c.<>9__0_0 = val; obj = (object)val; } MenuAPI.AddElementToSettingsMenu((BuilderDelegate)obj); } } [HarmonyPatch(typeof(SplashScreen), "Update")] internal static class SplashScreenSkipPatch { private static readonly FieldInfo StateField = AccessTools.Field(typeof(SplashScreen), "state"); private static readonly MethodInfo StateSetMethod = AccessTools.Method(typeof(SplashScreen), "StateSet", (Type[])null, (Type[])null); private static readonly Type StateType = AccessTools.Inner(typeof(SplashScreen), "State"); [HarmonyPostfix] public static void Postfix(SplashScreen __instance) { if (!Plugin.Enabled.Value) { return; } Gamepad current = Gamepad.current; if (current == null) { return; } int num = Convert.ToInt32(StateField.GetValue(__instance)); if (num <= 0 || num >= 3 || !AnyButtonDown(current)) { return; } try { StateSetMethod.Invoke(__instance, new object[1] { Enum.ToObject(StateType, 3) }); Plugin.Log.LogInfo((object)"[Gamepad] Splash screen skipped via controller."); } catch (Exception arg) { Plugin.Log.LogError((object)$"[Gamepad] Splash skip failed: {arg}"); } } private static bool AnyButtonDown(Gamepad gp) { if (!gp.buttonSouth.wasPressedThisFrame && !gp.buttonEast.wasPressedThisFrame && !gp.buttonWest.wasPressedThisFrame && !gp.buttonNorth.wasPressedThisFrame && !gp.startButton.wasPressedThisFrame) { return gp.selectButton.wasPressedThisFrame; } return true; } } [HarmonyPatch] internal static class ToggleInputPatch { private static readonly FieldRef ToggleSprintRef = AccessTools.FieldRefAccess("toggleSprint"); private static bool _movedSinceToggle; [HarmonyPatch(typeof(InputManager), "InputToggleGet")] [HarmonyPostfix] private static void InputToggleGetPostfix(InputKey key, ref bool __result) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 if (!__result && Plugin.Enabled.Value && Gamepad.current != null) { if ((int)key == 15 && Plugin.SprintToggle.Value) { __result = true; } else if ((int)key == 10 && Plugin.GrabToggle.Value) { __result = true; } else if ((int)key == 12 && Plugin.CrouchToggle.Value) { __result = true; } } } [HarmonyPatch(typeof(PlayerController), "FixedUpdate")] [HarmonyPostfix] private static void FixedUpdatePostfix(PlayerController __instance) { if (Plugin.Enabled.Value && Plugin.SprintToggle.Value && Gamepad.current != null) { if (!ToggleSprintRef.Invoke(__instance)) { _movedSinceToggle = false; } else if (__instance.moving) { _movedSinceToggle = true; } else if (_movedSinceToggle) { ToggleSprintRef.Invoke(__instance) = false; _movedSinceToggle = false; } } } } internal class VoiceIndicator : MonoBehaviour { private static readonly FieldRef VoiceChatRef; private static readonly FieldRef PushToTalkRef; private static readonly FieldRef ToggleMuteRef; private static readonly FieldRef InitialPositionRef; private static readonly bool RefsOk; private GameObject _icon; private static bool _cloneFailedThisScene; private static bool _warned; static VoiceIndicator() { try { VoiceChatRef = AccessTools.FieldRefAccess("voiceChat"); PushToTalkRef = AccessTools.FieldRefAccess("pushToTalk"); ToggleMuteRef = AccessTools.FieldRefAccess("toggleMute"); InitialPositionRef = AccessTools.FieldRefAccess("initialPosition"); RefsOk = true; } catch { RefsOk = false; } } internal static void ResetState() { _cloneFailedThisScene = false; } private void Update() { if (!Plugin.Enabled.Value || !Plugin.VoiceIndicatorEnabled.Value) { Hide(); return; } if (!RefsOk) { WarnOnce("vanilla voice fields not found"); return; } PlayerAvatar instance = PlayerAvatar.instance; AudioManager instance2 = AudioManager.instance; DataDirector instance3 = DataDirector.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || (Object)(object)instance3 == (Object)null) { Hide(); return; } bool flag; try { if ((Object)(object)VoiceChatRef.Invoke(instance) == (Object)null) { Hide(); return; } flag = PushToTalkRef.Invoke(instance2) && !ToggleMuteRef.Invoke(instance3) && !SemiFunc.InputHold((InputKey)25); } catch (Exception ex) { WarnOnce(ex.Message); return; } if (!flag) { Hide(); } else if ((!((Object)(object)_icon == (Object)null) || TryCreateClone()) && !_icon.activeSelf) { _icon.SetActive(true); } } private void Hide() { if ((Object)(object)_icon != (Object)null && _icon.activeSelf) { _icon.SetActive(false); } } private bool TryCreateClone() { //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_0047: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0128: Unknown result type (might be due to invalid IL or missing references) if (_cloneFailedThisScene) { return false; } try { ToggleMuteUI val = Object.FindObjectOfType(true); if ((Object)(object)val == (Object)null) { _cloneFailedThisScene = true; Plugin.Log.LogDebug((object)"[VoiceIndicator] No ToggleMuteUI widget in this scene -- no indicator here."); return false; } Vector3 val2 = InitialPositionRef.Invoke((SemiUI)(object)val); if (val2 == Vector3.zero && !((Behaviour)val).isActiveAndEnabled) { val2 = ((Component)val).transform.localPosition; } GameObject gameObject = ((Component)val).gameObject; _icon = Object.Instantiate(gameObject, gameObject.transform.parent); ((Object)_icon).name = "NativeController.VoiceIndicator"; Object.Destroy((Object)(object)_icon.GetComponent()); foreach (Transform item in _icon.transform) { ((Component)item).gameObject.SetActive(true); } TMP_Text[] componentsInChildren = _icon.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = true; } _icon.transform.localPosition = val2; _icon.SetActive(false); Plugin.Log.LogDebug((object)"[VoiceIndicator] Cloned the mute widget (shared spot)."); return true; } catch (Exception ex) { if ((Object)(object)_icon != (Object)null) { Object.Destroy((Object)(object)_icon); } _icon = null; _cloneFailedThisScene = true; WarnOnce(ex.Message); return false; } } private static void WarnOnce(string why) { if (!_warned) { _warned = true; Plugin.Log.LogWarning((object)("[VoiceIndicator] Disabled (" + why + ") -- further warnings suppressed.")); } } } }