using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.Utilities; using UnityEngine.SceneManagement; using UnityEngine.UI; [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: AssemblyCompany("MycopunkModder")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Makes all semi-auto weapons fully automatic")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0.0")] [assembly: AssemblyProduct("FullAutoMod")] [assembly: AssemblyTitle("FullAutoMod")] [assembly: AssemblyVersion("1.0.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 FullAutoMod { [BepInPlugin("fullautomod.mycopunk", "FullAutoMod", "1.0.0.0")] [BepInProcess("Mycopunk.exe")] [MycoMod(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private enum FireMode { Default, ForceFullAuto } [HarmonyPatch] private class PatchGunUpdate { private static MethodBase TargetMethod() { return _gunUpdate; } [HarmonyPrefix] private static void Prefix(object __instance) { if (!_resolved || __instance == null) { return; } int hashCode = __instance.GetHashCode(); if (!_gunFireModes.TryGetValue(hashCode, out var value) || value != FireMode.ForceFullAuto || !_fireActionHooked || _fireAction == null) { return; } bool flag; try { flag = _fireAction.IsPressed(); } catch { _fireActionHooked = false; _fireAction = null; return; } if (!flag) { return; } object obj2; try { obj2 = _gunPlayer?.GetValue(__instance, null); } catch { return; } if (obj2 == null) { return; } bool flag2; try { flag2 = (bool)_gunActive.GetValue(__instance, null); } catch { return; } if (!flag2) { return; } float num; bool flag3; try { num = (float)_gunRemainingAmmo.GetValue(__instance, null); flag3 = (bool)_gunCanFireWithoutAmmo.GetValue(__instance, null); } catch { return; } if (!(num <= 0f) || flag3) { bool flag4; try { flag4 = (bool)_gunReloading.GetValue(__instance, null); } catch { return; } if (!flag4) { _gunIsFireInputHeld.SetValue(__instance, true); } } } } public const string PluginGUID = "fullautomod.mycopunk"; public const string PluginName = "FullAutoMod"; public const string PluginVersion = "1.0.0.0"; internal static ManualLogSource Logger; private static ConfigEntry _toggleKeyConfig; private static ConfigEntry _popupYOffsetConfig; private static Type _gunType; private static MethodInfo _gunUpdate; private static FieldInfo _gunIsFireInputHeld; private static PropertyInfo _gunRemainingAmmo; private static PropertyInfo _gunCanFireWithoutAmmo; private static PropertyInfo _gunReloading; private static PropertyInfo _gunPlayer; private static PropertyInfo _gunActive; private static bool _resolved; private static InputAction _fireAction; private static bool _fireActionHooked; private static readonly Dictionary _gunFireModes = new Dictionary(); private static object _cachedGun; private static float _lastGunQuery; private const float GUN_CACHE = 0.25f; private static bool _toggleKeyDown; private static bool _toggleKeyWasDown; private static float _toggleHoldTime; private const float TOGGLE_HOLD_THRESHOLD = 1f; private static bool _toggleExecutedAsHold; private static string _cachedKeyName = ""; private static Key _cachedInputSystemKey; private static bool _toggleKeyParseWarned; private static GameObject _popupCanvas; private static Text _popupText; private static CanvasGroup _popupGroup; private static RectTransform _popupBgRect; private static float _popupShowTime; private const float POPUP_AUTO_FADE = 0.5f; private static bool _popupReady; private static FileSystemWatcher _configWatcher; private static volatile bool _pendingConfigReload; private static Key ParseKeyName(string name) { //IL_000d: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(name)) { return (Key)10; } if (Enum.TryParse(name, ignoreCase: true, out Key result)) { return result; } return (Key)10; } private static Key GetCurrentToggleKey() { //IL_0085: 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_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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) try { string value = _toggleKeyConfig.Value; if (value != _cachedKeyName) { _cachedKeyName = value; _cachedInputSystemKey = ParseKeyName(value); Logger.LogDebug((object)$"ToggleKey re-parsed: \"{value}\" → {_cachedInputSystemKey}"); } return _cachedInputSystemKey; } catch { if (!_toggleKeyParseWarned) { _toggleKeyParseWarned = true; ManualLogSource logger = Logger; if (logger != null) { logger.LogWarning((object)"Failed to read ToggleKey from config; falling back to Backslash"); } } return (Key)10; } } private void Awake() { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_00db: 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) Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"Full Auto Mod loading..."); _toggleKeyConfig = ((BaseUnityPlugin)this).Config.Bind("General", "ToggleKey", "Backslash", "Key to toggle fire mode per weapon.\nUse standard key names (Backslash, I, F10, Space, etc.).\nQuick press (< 1s): toggle fire mode on release.\nHold (>= 1s): preview current mode popup."); _popupYOffsetConfig = ((BaseUnityPlugin)this).Config.Bind("UI", "PopupYOffset", 60, new ConfigDescription("Vertical offset of the fire mode popup (positive = below crosshair)", (AcceptableValueBase)(object)new AcceptableValueRange(-200, 200), Array.Empty())); ((BaseUnityPlugin)this).Config.Save(); _toggleKeyConfig.SettingChanged += delegate { _cachedKeyName = ""; Logger.LogInfo((object)"ToggleKey config changed — applying immediately."); }; _popupYOffsetConfig.SettingChanged += delegate { UpdatePopupPosition(); Logger.LogDebug((object)"PopupYOffset config changed — repositioning."); }; _cachedKeyName = _toggleKeyConfig.Value; _cachedInputSystemKey = ParseKeyName(_cachedKeyName); try { _configWatcher = new FileSystemWatcher(Paths.ConfigPath, "fullautomod.mycopunk.cfg") { NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite), EnableRaisingEvents = true }; _configWatcher.Changed += OnConfigFileChanged; _configWatcher.Created += OnConfigFileChanged; _configWatcher.Renamed += OnConfigFileChanged; Logger.LogInfo((object)"Config file watcher started."); } catch (Exception ex) { Logger.LogWarning((object)("Could not start config file watcher: " + ex.Message)); } ResolveGunType(); if (_resolved) { Harmony.CreateAndPatchAll(typeof(PatchGunUpdate), (string)null); } SceneManager.sceneLoaded += OnSceneLoaded; CreatePopupUI(); Logger.LogInfo((object)"Full Auto Mod initialized."); Logger.LogInfo((object)("Toggle key: \"" + _cachedKeyName + "\" (live config, no restart needed)")); } private void OnConfigFileChanged(object sender, FileSystemEventArgs e) { _pendingConfigReload = true; } private void OnDestroy() { if (_configWatcher != null) { _configWatcher.EnableRaisingEvents = false; _configWatcher.Changed -= OnConfigFileChanged; _configWatcher.Created -= OnConfigFileChanged; _configWatcher.Renamed -= OnConfigFileChanged; _configWatcher.Dispose(); _configWatcher = null; } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { _fireActionHooked = false; _fireAction = null; _cachedGun = null; _gunFireModes.Clear(); } private void Update() { //IL_0097: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Invalid comparison between Unknown and I4 //IL_00af: Unknown result type (might be due to invalid IL or missing references) if (_pendingConfigReload) { _pendingConfigReload = false; try { ((BaseUnityPlugin)this).Config.Reload(); Logger.LogInfo((object)"Config reloaded from disk."); } catch (Exception ex) { Logger.LogError((object)("Error reloading config: " + ex.Message)); } } if (!_resolved) { ResolveGunType(); return; } if (!_fireActionHooked) { HookFireAction(); } bool flag = false; if (Keyboard.current != null) { Key currentToggleKey = GetCurrentToggleKey(); if ((int)currentToggleKey > 0) { KeyControl val = Keyboard.current[currentToggleKey]; if (val != null) { flag = ((ButtonControl)val).isPressed; } } } if (flag && !_toggleKeyWasDown) { _toggleHoldTime = 0f; _toggleExecutedAsHold = false; } if (flag) { _toggleHoldTime += Time.unscaledDeltaTime; if (_toggleHoldTime >= 1f && !_toggleExecutedAsHold) { _toggleExecutedAsHold = true; object obj = FindHeldGun(); if (obj != null) { ShowPopup(GetCurrentModeLabel(obj), keepOpen: true); } } } if (!flag && _toggleKeyWasDown) { if (_toggleHoldTime < 1f) { OnTogglePressed(); } else if (_toggleExecutedAsHold) { HidePopup(); } _toggleHoldTime = 0f; _toggleExecutedAsHold = false; } _toggleKeyDown = flag; _toggleKeyWasDown = flag; if (_popupReady && (Object)(object)_popupGroup != (Object)null && _popupGroup.alpha > 0f && !_toggleKeyDown) { float num = Time.unscaledTime - _popupShowTime; if (num > 1f) { _popupGroup.alpha = 0f; _popupCanvas.SetActive(false); } else if (num > 0.5f) { float num2 = (num - 0.5f) / 0.5f; _popupGroup.alpha = 1f - num2; } } } private string GetCurrentModeLabel(object gun) { int hashCode = gun.GetHashCode(); FireMode fireMode = FireMode.Default; if (_gunFireModes.TryGetValue(hashCode, out var value)) { fireMode = value; } if (fireMode == FireMode.ForceFullAuto) { return "Full-Auto (Override)"; } return GetDefaultModeLabel(gun); } private void OnTogglePressed() { object obj = FindHeldGun(); if (obj != null) { int hashCode = obj.GetHashCode(); FireMode fireMode = FireMode.Default; if (_gunFireModes.TryGetValue(hashCode, out var value)) { fireMode = value; } if (fireMode == FireMode.Default) { _gunFireModes[hashCode] = FireMode.ForceFullAuto; ShowPopup("Full-Auto (Override)", keepOpen: false); } else { _gunFireModes.Remove(hashCode); ShowPopup(GetDefaultModeLabel(obj), keepOpen: false); } } } private static string GetDefaultModeLabel(object gun) { return "Default"; } private void CreatePopupUI() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0059: 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_00a2: Expected O, but got Unknown //IL_00d3: 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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Expected O, but got Unknown //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) try { _popupCanvas = new GameObject("FAM_PopupCanvas"); Object.DontDestroyOnLoad((Object)(object)_popupCanvas); Canvas val = _popupCanvas.AddComponent(); val.renderMode = (RenderMode)0; val.sortingOrder = 31000; CanvasScaler val2 = _popupCanvas.AddComponent(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = new Vector2(1920f, 1080f); val2.screenMatchMode = (ScreenMatchMode)0; val2.matchWidthOrHeight = 0.5f; _popupGroup = _popupCanvas.AddComponent(); _popupGroup.alpha = 0f; GameObject val3 = new GameObject("PopupBG"); val3.transform.SetParent(_popupCanvas.transform, false); _popupBgRect = val3.AddComponent(); _popupBgRect.anchorMin = new Vector2(0.5f, 0.5f); _popupBgRect.anchorMax = new Vector2(0.5f, 0.5f); _popupBgRect.pivot = new Vector2(0.5f, 0.5f); _popupBgRect.sizeDelta = new Vector2(260f, 34f); UpdatePopupPosition(); Image val4 = val3.AddComponent(); ((Graphic)val4).color = new Color(0.015f, 0.015f, 0.018f, 0.82f); GameObject val5 = new GameObject("PopupText"); val5.transform.SetParent(val3.transform, false); RectTransform val6 = val5.AddComponent(); val6.anchorMin = Vector2.zero; val6.anchorMax = Vector2.one; val6.offsetMin = Vector2.zero; val6.offsetMax = Vector2.zero; _popupText = val5.AddComponent(); _popupText.font = Resources.GetBuiltinResource("Arial.ttf"); _popupText.fontSize = 18; _popupText.fontStyle = (FontStyle)1; _popupText.alignment = (TextAnchor)4; ((Graphic)_popupText).color = Color.white; _popupText.text = ""; _popupCanvas.SetActive(false); _popupReady = true; } catch (Exception ex) { Logger.LogError((object)("CreatePopupUI: " + ex.Message)); } } private void UpdatePopupPosition() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_popupBgRect != (Object)null) { float num = ((_popupYOffsetConfig != null) ? _popupYOffsetConfig.Value : 60); _popupBgRect.anchoredPosition = new Vector2(0f, 0f - num); } } private void ShowPopup(string text, bool keepOpen) { if (_popupReady && !((Object)(object)_popupText == (Object)null) && !((Object)(object)_popupGroup == (Object)null)) { UpdatePopupPosition(); _popupText.text = text; _popupGroup.alpha = 1f; _popupCanvas.SetActive(true); if (!keepOpen) { _popupShowTime = Time.unscaledTime; } } } private void HidePopup() { if (_popupReady && !((Object)(object)_popupGroup == (Object)null)) { _popupGroup.alpha = 0f; _popupCanvas.SetActive(false); } } private static object FindHeldGun() { float unscaledTime = Time.unscaledTime; if (_cachedGun != null && unscaledTime - _lastGunQuery < 0.25f) { return _cachedGun; } _lastGunQuery = unscaledTime; _cachedGun = null; Type type = Type.GetType("Pigeon.Movement.Player, Assembly-CSharp"); if (type == null) { return null; } PropertyInfo property = type.GetProperty("LocalPlayer", BindingFlags.Static | BindingFlags.Public); if (property == null) { return null; } object value = property.GetValue(null, null); if (value == null) { return null; } Object[] array = Resources.FindObjectsOfTypeAll(_gunType); Object[] array2 = array; foreach (object obj in array2) { if (obj == null) { continue; } try { object obj2 = _gunPlayer?.GetValue(obj, null); bool flag = (bool)(_gunActive?.GetValue(obj, null) ?? ((object)false)); if (obj2 == value && flag) { _cachedGun = obj; return obj; } } catch { } } return null; } private void ResolveGunType() { try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.GetName().Name != "Assembly-CSharp") { continue; } _gunType = assembly.GetType("Gun"); if (_gunType == null) { Logger.LogWarning((object)"Gun not found"); break; } Logger.LogInfo((object)("Gun: " + _gunType.FullName)); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; _gunUpdate = _gunType.GetMethod("Update", bindingAttr); _gunIsFireInputHeld = _gunType.GetField("isFireInputHeld", bindingAttr); _gunRemainingAmmo = _gunType.GetProperty("RemainingAmmo", bindingAttr); _gunCanFireWithoutAmmo = _gunType.GetProperty("CanFireWithoutAmmo", bindingAttr); _gunReloading = _gunType.GetProperty("Reloading", bindingAttr); _gunPlayer = _gunType.GetProperty("Player", bindingAttr); _gunActive = _gunType.GetProperty("Active", bindingAttr); if (_gunUpdate == null || _gunIsFireInputHeld == null) { Logger.LogError((object)"Missing critical members"); } else { _resolved = true; } break; } } catch (Exception ex) { Logger.LogError((object)("Init: " + ex.Message)); } } private void HookFireAction() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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) try { InputActionAsset[] array = Resources.FindObjectsOfTypeAll(); InputActionAsset[] array2 = array; foreach (InputActionAsset val in array2) { Enumerator enumerator = val.actionMaps.GetEnumerator(); try { while (enumerator.MoveNext()) { InputActionMap current = enumerator.Current; if (_fireAction == null) { _fireAction = current.FindAction("Fire", false); if (_fireAction != null) { _fireAction.Enable(); } } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } } if (_fireAction != null) { _fireActionHooked = true; } } catch (Exception ex) { Logger.LogWarning((object)("HookFire: " + ex.Message)); } } } }