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<string> _toggleKeyConfig;
private static ConfigEntry<int> _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<int, FireMode> _gunFireModes = new Dictionary<int, FireMode>();
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<Key>(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<string>("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<int>("UI", "PopupYOffset", 60, new ConfigDescription("Vertical offset of the fire mode popup (positive = below crosshair)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-200, 200), Array.Empty<object>()));
((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<Canvas>();
val.renderMode = (RenderMode)0;
val.sortingOrder = 31000;
CanvasScaler val2 = _popupCanvas.AddComponent<CanvasScaler>();
val2.uiScaleMode = (ScaleMode)1;
val2.referenceResolution = new Vector2(1920f, 1080f);
val2.screenMatchMode = (ScreenMatchMode)0;
val2.matchWidthOrHeight = 0.5f;
_popupGroup = _popupCanvas.AddComponent<CanvasGroup>();
_popupGroup.alpha = 0f;
GameObject val3 = new GameObject("PopupBG");
val3.transform.SetParent(_popupCanvas.transform, false);
_popupBgRect = val3.AddComponent<RectTransform>();
_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<Image>();
((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<RectTransform>();
val6.anchorMin = Vector2.zero;
val6.anchorMax = Vector2.one;
val6.offsetMin = Vector2.zero;
val6.offsetMax = Vector2.zero;
_popupText = val5.AddComponent<Text>();
_popupText.font = Resources.GetBuiltinResource<Font>("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>();
InputActionAsset[] array2 = array;
foreach (InputActionAsset val in array2)
{
Enumerator<InputActionMap> 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));
}
}
}
}