using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.0.0.0")] namespace ControllerChords; [BepInPlugin("marc.valheim.controllerchords", "Controller Chords", "0.2.0")] [BepInProcess("valheim.exe")] public sealed class ControllerChordsPlugin : BaseUnityPlugin { private sealed class ChordSlot { public int Index; public ConfigEntry Enabled; public ConfigEntry Modifier; public ConfigEntry Button; public ConfigEntry TargetKey; public ConfigEntry BlockModifierDefaultAction; public ConfigEntry VirtualPressFrames; public ConfigEntry HoldMode; } private struct ChordDefaults { public readonly bool Enabled; public readonly ControllerButton Modifier; public readonly ControllerButton Button; public readonly KeyCode TargetKey; public readonly bool BlockModifierDefaultAction; public readonly int VirtualPressFrames; public ChordDefaults(bool enabled, ControllerButton modifier, ControllerButton button, KeyCode targetKey, bool blockModifierDefaultAction, int virtualPressFrames) { //IL_0017: 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) Enabled = enabled; Modifier = modifier; Button = button; TargetKey = targetKey; BlockModifierDefaultAction = blockModifierDefaultAction; VirtualPressFrames = virtualPressFrames; } } public const string PluginGuid = "marc.valheim.controllerchords"; public const string PluginName = "Controller Chords"; public const string PluginVersion = "0.2.0"; private const int SlotCount = 12; private const int MinimumVirtualPressFrames = 1; private const int MaximumVirtualPressFrames = 8; internal static ControllerChordsPlugin Instance; private ConfigEntry enabledConfig; private ConfigEntry allowInMenus; private ConfigEntry logChordEvents; private readonly List slots = new List(12); private readonly Dictionary virtualKeyFrames = new Dictionary(); private readonly Dictionary virtualButtonFrames = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly Dictionary blockedButtonFrames = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly List keyScratch = new List(); private readonly List stringScratch = new List(); private readonly HashSet heldChordActive = new HashSet(); private Harmony harmony; private Type zInputType; private Func zGetButton; private Func zGetButtonDown; private PropertyInfo zVirtualKeyboardOpenProperty; private MethodInfo menuIsVisibleMethod; private MethodInfo inventoryGuiIsVisibleMethod; private MethodInfo storeGuiIsVisibleMethod; private MethodInfo textInputIsVisibleMethod; private MethodInfo consoleIsVisibleMethod; private bool zInputReady; private bool patchesInstalled; private int chordsFired; private void Awake() { Instance = this; BindConfig(); if (!enabledConfig.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Controller Chords is disabled by config. No Harmony patches were installed."); return; } ResolveZInput(); ResolveMenuGuards(); InstallPatches(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Controller Chords 0.2.0 loaded. Chord detection uses Valheim ZInput when available."); } private void OnDestroy() { if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } virtualKeyFrames.Clear(); virtualButtonFrames.Clear(); blockedButtonFrames.Clear(); if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void Update() { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Invalid comparison between Unknown and I4 if (!enabledConfig.Value || !zInputReady || (!allowInMenus.Value && IsMenuInputContext())) { return; } for (int i = 0; i < slots.Count; i++) { ChordSlot chordSlot = slots[i]; if (chordSlot == null || !chordSlot.Enabled.Value) { continue; } ControllerButton value = chordSlot.Modifier.Value; if (!IsSupportedModifier(value)) { continue; } ControllerButton value2 = chordSlot.Button.Value; if (value2 == ControllerButton.None || value2 == value || (int)chordSlot.TargetKey.Value == 0) { continue; } string text = ToZInputButtonName(value); string text2 = ToZInputButtonName(value2); if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(text2)) { continue; } bool flag = SafeGetZButton(text); if (chordSlot.HoldMode.Value) { bool flag2 = SafeGetZButton(text2); if (flag && flag2) { HoldChord(chordSlot, text); } else if (heldChordActive.Contains(chordSlot.Index)) { heldChordActive.Remove(chordSlot.Index); if (logChordEvents.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Controller Chords: chord " + chordSlot.Index + " HOLD released.")); } } } else { bool flag3 = SafeGetZButtonDown(text2); if (flag && flag3) { FireChord(chordSlot, text); } } } } private void LateUpdate() { AgeKeyFrames(); AgeStringFrames(virtualButtonFrames); AgeStringFrames(blockedButtonFrames); } private void BindConfig() { //IL_010a: Unknown result type (might be due to invalid IL or missing references) enabledConfig = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Master switch. If false at startup, Controller Chords installs no active input patches."); allowInMenus = ((BaseUnityPlugin)this).Config.Bind("General", "AllowInMenus", false, "Allow controller chords while Valheim menus/text input are open."); logChordEvents = ((BaseUnityPlugin)this).Config.Bind("General", "LogChordEvents", false, "Log each fired chord to BepInEx/LogOutput.log."); for (int i = 1; i <= 12; i++) { ChordDefaults defaults = GetDefaults(i); string text = "Chord " + i.ToString("00"); ChordSlot item = new ChordSlot { Index = i, Enabled = ((BaseUnityPlugin)this).Config.Bind(text, "Enabled", defaults.Enabled, "Enable this controller chord slot."), Modifier = ((BaseUnityPlugin)this).Config.Bind(text, "Modifier", defaults.Modifier, "Held modifier button. Supported modifiers are RB, LB, RT, and LT."), Button = ((BaseUnityPlugin)this).Config.Bind(text, "Button", defaults.Button, "Trigger button that fires on button-down while the modifier is held."), TargetKey = ((BaseUnityPlugin)this).Config.Bind(text, "TargetKey", defaults.TargetKey, "Keyboard KeyCode exposed virtually to other mods."), BlockModifierDefaultAction = ((BaseUnityPlugin)this).Config.Bind(text, "BlockModifierDefaultAction", defaults.BlockModifierDefaultAction, "Temporarily suppress this modifier's ZInput action when the chord fires. Defaults false."), VirtualPressFrames = ((BaseUnityPlugin)this).Config.Bind(text, "VirtualPressFrames", defaults.VirtualPressFrames, "Number of frames the virtual key remains visible to input queries (tap mode only)."), HoldMode = ((BaseUnityPlugin)this).Config.Bind(text, "HoldMode", false, "When true, the target key is held DOWN for as long as you hold the chord (modifier + trigger), and released when you let go. Use this for press-and-hold mods like climbing. When false (default), the chord sends a brief tap suitable for toggle hotkeys.") }; slots.Add(item); } } private static ChordDefaults GetDefaults(int index) { return index switch { 1 => new ChordDefaults(enabled: true, ControllerButton.RB, ControllerButton.A, (KeyCode)306, blockModifierDefaultAction: false, 2), 2 => new ChordDefaults(enabled: false, ControllerButton.RB, ControllerButton.B, (KeyCode)308, blockModifierDefaultAction: false, 2), 3 => new ChordDefaults(enabled: false, ControllerButton.RB, ControllerButton.X, (KeyCode)103, blockModifierDefaultAction: false, 2), 4 => new ChordDefaults(enabled: false, ControllerButton.RB, ControllerButton.Y, (KeyCode)104, blockModifierDefaultAction: false, 2), 5 => new ChordDefaults(enabled: false, ControllerButton.LB, ControllerButton.A, (KeyCode)106, blockModifierDefaultAction: false, 2), 6 => new ChordDefaults(enabled: false, ControllerButton.LB, ControllerButton.B, (KeyCode)107, blockModifierDefaultAction: false, 2), 7 => new ChordDefaults(enabled: false, ControllerButton.LB, ControllerButton.X, (KeyCode)108, blockModifierDefaultAction: false, 2), 8 => new ChordDefaults(enabled: false, ControllerButton.LB, ControllerButton.Y, (KeyCode)59, blockModifierDefaultAction: false, 2), 9 => new ChordDefaults(enabled: false, ControllerButton.RT, ControllerButton.DPadUp, (KeyCode)287, blockModifierDefaultAction: false, 2), 10 => new ChordDefaults(enabled: false, ControllerButton.RT, ControllerButton.DPadDown, (KeyCode)288, blockModifierDefaultAction: false, 2), 11 => new ChordDefaults(enabled: false, ControllerButton.LT, ControllerButton.DPadLeft, (KeyCode)289, blockModifierDefaultAction: false, 2), _ => new ChordDefaults(enabled: false, ControllerButton.LT, ControllerButton.DPadRight, (KeyCode)290, blockModifierDefaultAction: false, 2), }; } private void ResolveZInput() { zInputType = FindType("ZInput"); if (zInputType == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Controller Chords: ZInput type was not found. Controller chord detection is disabled, but Unity key patches can still load safely."); return; } zGetButton = CreateStringBoolDelegate(zInputType, "GetButton"); zGetButtonDown = CreateStringBoolDelegate(zInputType, "GetButtonDown"); zVirtualKeyboardOpenProperty = zInputType.GetProperty("VirtualKeyboardOpen", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); zInputReady = zGetButton != null && zGetButtonDown != null; if (!zInputReady) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Controller Chords: ZInput.GetButton/GetButtonDown were not found. Controller chord detection is disabled."); } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Controller Chords: ZInput button reading resolved OK (GetButton/GetButtonDown bound). Chord detection active."); } } private void ResolveMenuGuards() { menuIsVisibleMethod = FindStaticBoolMethod("Menu", "IsVisible"); inventoryGuiIsVisibleMethod = FindStaticBoolMethod("InventoryGui", "IsVisible"); storeGuiIsVisibleMethod = FindStaticBoolMethod("StoreGui", "IsVisible"); textInputIsVisibleMethod = FindStaticBoolMethod("TextInput", "IsVisible"); consoleIsVisibleMethod = FindStaticBoolMethod("Console", "IsVisible"); } private void InstallPatches() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown harmony = new Harmony("marc.valheim.controllerchords"); TryPatchPostfix(typeof(Input).GetMethod("GetKeyDown", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(KeyCode) }, null), "InputKeyPostfix", "UnityEngine.Input.GetKeyDown(KeyCode)"); TryPatchPostfix(typeof(Input).GetMethod("GetKey", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(KeyCode) }, null), "InputKeyPostfix", "UnityEngine.Input.GetKey(KeyCode)"); if (zInputType != null) { TryPatchPostfix(zInputType.GetMethod("GetKeyDown", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(KeyCode), typeof(bool) }, null), "ZInputKeyPostfix", "ZInput.GetKeyDown(KeyCode,bool)"); TryPatchPostfix(zInputType.GetMethod("GetKey", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(KeyCode), typeof(bool) }, null), "ZInputKeyPostfix", "ZInput.GetKey(KeyCode,bool)"); TryPatchPostfix(zInputType.GetMethod("GetButtonDown", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null), "ZInputButtonPostfix", "ZInput.GetButtonDown(string)"); TryPatchPostfix(zInputType.GetMethod("GetButton", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null), "ZInputButtonPostfix", "ZInput.GetButton(string)"); } } private void TryPatchPostfix(MethodInfo target, string postfixName, string label) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown if (target == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Controller Chords: could not find " + label + "; this compatibility patch is disabled.")); return; } try { MethodInfo method = typeof(ControllerChordsPlugin).GetMethod(postfixName, BindingFlags.Static | BindingFlags.NonPublic); harmony.Patch((MethodBase)target, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); patchesInstalled = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Controller Chords: patched " + label + ".")); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Controller Chords: failed to patch " + label + ": " + ex.Message)); } } private unsafe void HoldChord(ChordSlot slot, string modifierName) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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) KeyCode value = slot.TargetKey.Value; SetMaxFrameCount(virtualKeyFrames, value, 2); AddVirtualButtonName(value, 2); if (slot.BlockModifierDefaultAction.Value && !string.IsNullOrEmpty(modifierName)) { SetMaxFrameCount(blockedButtonFrames, modifierName, 2); } if (logChordEvents.Value && !heldChordActive.Contains(slot.Index)) { heldChordActive.Add(slot.Index); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Controller Chords: chord " + slot.Index + " HOLD started " + slot.Modifier.Value.ToString() + "+" + slot.Button.Value.ToString() + " -> " + ((object)(*(KeyCode*)(&value))/*cast due to .constrained prefix*/).ToString() + " (held until released).")); } } private unsafe void FireChord(ChordSlot slot, string modifierName) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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) int frames = Mathf.Clamp(slot.VirtualPressFrames.Value, 1, 8); KeyCode value = slot.TargetKey.Value; SetMaxFrameCount(virtualKeyFrames, value, frames); AddVirtualButtonName(value, frames); if (slot.BlockModifierDefaultAction.Value && !string.IsNullOrEmpty(modifierName)) { SetMaxFrameCount(blockedButtonFrames, modifierName, frames); } chordsFired++; if (logChordEvents.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Controller Chords: chord " + slot.Index + " fired " + slot.Modifier.Value.ToString() + "+" + slot.Button.Value.ToString() + " -> " + ((object)(*(KeyCode*)(&value))/*cast due to .constrained prefix*/).ToString() + " for " + frames + " frame(s).")); } } private unsafe void AddVirtualButtonName(KeyCode key, int frames) { string text = ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); SetMaxFrameCount(virtualButtonFrames, text, frames); SetMaxFrameCount(virtualButtonFrames, text.ToLowerInvariant(), frames); } private bool IsVirtualKeyActive(KeyCode key) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) int value; return enabledConfig.Value && virtualKeyFrames.TryGetValue(key, out value) && value > 0; } private bool IsVirtualButtonActive(string name) { if (string.IsNullOrEmpty(name) || !enabledConfig.Value) { return false; } int value; return virtualButtonFrames.TryGetValue(name, out value) && value > 0; } private bool IsButtonBlocked(string name) { if (string.IsNullOrEmpty(name) || !enabledConfig.Value) { return false; } int value; return blockedButtonFrames.TryGetValue(name, out value) && value > 0; } private bool SafeGetZButton(string name) { try { return zGetButton != null && zGetButton(name); } catch (Exception ex) { zInputReady = false; ((BaseUnityPlugin)this).Logger.LogWarning((object)("Controller Chords: ZInput.GetButton failed and chord detection was disabled: " + ex.Message)); return false; } } private bool SafeGetZButtonDown(string name) { try { return zGetButtonDown != null && zGetButtonDown(name); } catch (Exception ex) { zInputReady = false; ((BaseUnityPlugin)this).Logger.LogWarning((object)("Controller Chords: ZInput.GetButtonDown failed and chord detection was disabled: " + ex.Message)); return false; } } private bool IsMenuInputContext() { if (TryReadStaticBoolProperty(zVirtualKeyboardOpenProperty)) { return true; } return TryInvokeBool(menuIsVisibleMethod) || TryInvokeBool(inventoryGuiIsVisibleMethod) || TryInvokeBool(storeGuiIsVisibleMethod) || TryInvokeBool(textInputIsVisibleMethod) || TryInvokeBool(consoleIsVisibleMethod); } private static bool TryInvokeBool(MethodInfo method) { if (method == null) { return false; } try { object obj = method.Invoke(null, null); return obj is bool && (bool)obj; } catch { return false; } } private static bool TryReadStaticBoolProperty(PropertyInfo property) { if (property == null) { return false; } try { object value = property.GetValue(null, null); return value is bool && (bool)value; } catch { return false; } } private static Type FindType(string typeName) { Type type = Type.GetType(typeName, throwOnError: false); if (type != null) { return type; } Type type2 = Type.GetType(typeName + ", assembly_utils", throwOnError: false); if (type2 != null) { return type2; } Type type3 = Type.GetType(typeName + ", assembly_valheim", throwOnError: false); if (type3 != null) { return type3; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type4 = assemblies[i].GetType(typeName, throwOnError: false); if (type4 != null) { return type4; } } return null; } private static MethodInfo FindStaticBoolMethod(string typeName, string methodName) { Type type = FindType(typeName); if (type == null) { return null; } MethodInfo method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); return (method != null && method.ReturnType == typeof(bool)) ? method : null; } private Func CreateStringBoolDelegate(Type type, string methodName) { MethodInfo method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); if (method != null && method.ReturnType == typeof(bool)) { try { return (Func)Delegate.CreateDelegate(typeof(Func), method); } catch { } } MethodInfo instanceMethod = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); if (instanceMethod == null || instanceMethod.ReturnType != typeof(bool)) { return null; } PropertyInfo instanceProperty = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo instanceField = ((instanceProperty == null) ? type.GetField("m_instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : null); if (instanceProperty == null && instanceField == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Controller Chords: found instance method ZInput." + methodName + " but no static 'instance' accessor; chord detection disabled.")); return null; } return delegate(string name) { object obj2 = ((instanceProperty != null) ? instanceProperty.GetValue(null, null) : instanceField.GetValue(null)); if (obj2 == null) { return false; } object obj3 = instanceMethod.Invoke(obj2, new object[1] { name }); bool flag = default(bool); int num; if (obj3 is bool) { flag = (bool)obj3; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; }; } private void AgeKeyFrames() { //IL_0045: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_00a4: Unknown result type (might be due to invalid IL or missing references) if (virtualKeyFrames.Count == 0) { return; } keyScratch.Clear(); foreach (KeyValuePair virtualKeyFrame in virtualKeyFrames) { keyScratch.Add(virtualKeyFrame.Key); } for (int i = 0; i < keyScratch.Count; i++) { KeyCode key = keyScratch[i]; int num = virtualKeyFrames[key] - 1; if (num <= 0) { virtualKeyFrames.Remove(key); } else { virtualKeyFrames[key] = num; } } } private void AgeStringFrames(Dictionary framesByName) { if (framesByName.Count == 0) { return; } stringScratch.Clear(); foreach (KeyValuePair item in framesByName) { stringScratch.Add(item.Key); } for (int i = 0; i < stringScratch.Count; i++) { string key = stringScratch[i]; int num = framesByName[key] - 1; if (num <= 0) { framesByName.Remove(key); } else { framesByName[key] = num; } } } private static void SetMaxFrameCount(Dictionary dictionary, KeyCode key, int frames) { //IL_0002: 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) if (!dictionary.TryGetValue(key, out var value) || value < frames) { dictionary[key] = frames; } } private static void SetMaxFrameCount(Dictionary dictionary, string key, int frames) { if (!string.IsNullOrEmpty(key) && (!dictionary.TryGetValue(key, out var value) || value < frames)) { dictionary[key] = frames; } } private static bool IsSupportedModifier(ControllerButton button) { return button == ControllerButton.RB || button == ControllerButton.LB || button == ControllerButton.RT || button == ControllerButton.LT; } private static string ToZInputButtonName(ControllerButton button) { return button switch { ControllerButton.A => "JoyButtonA", ControllerButton.B => "JoyButtonB", ControllerButton.X => "JoyButtonX", ControllerButton.Y => "JoyButtonY", ControllerButton.DPadLeft => "JoyDPadLeft", ControllerButton.DPadRight => "JoyDPadRight", ControllerButton.DPadUp => "JoyDPadUp", ControllerButton.DPadDown => "JoyDPadDown", ControllerButton.LB => "JoyLBumper", ControllerButton.RB => "JoyRBumper", ControllerButton.LT => "JoyLTrigger", ControllerButton.RT => "JoyRTrigger", ControllerButton.LeftStick => "JoyLStick", ControllerButton.RightStick => "JoyRStick", ControllerButton.Back => "JoyBack", ControllerButton.Start => "JoyStart", _ => string.Empty, }; } private static void InputKeyPostfix(KeyCode __0, ref bool __result) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) ControllerChordsPlugin instance = Instance; if (!__result && !((Object)(object)instance == (Object)null) && instance.patchesInstalled && instance.IsVirtualKeyActive(__0)) { __result = true; } } private static void ZInputKeyPostfix(KeyCode __0, ref bool __result) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) ControllerChordsPlugin instance = Instance; if (!__result && !((Object)(object)instance == (Object)null) && instance.patchesInstalled && instance.IsVirtualKeyActive(__0)) { __result = true; } } private static void ZInputButtonPostfix(string __0, ref bool __result) { ControllerChordsPlugin instance = Instance; if (!((Object)(object)instance == (Object)null) && instance.patchesInstalled) { if (instance.IsButtonBlocked(__0)) { __result = false; } else if (!__result && instance.IsVirtualButtonActive(__0)) { __result = true; } } } } public enum ControllerButton { None, A, B, X, Y, DPadLeft, DPadRight, DPadUp, DPadDown, LB, RB, LT, RT, LeftStick, RightStick, Back, Start }